
Суть его простая - найти подходящие элементы, обернуть и добавить необходимые блоки, организовать тип вывода подсказки - по клику или при наведении курсора и самое главное - всегда отображать подсказку в видимой области экрана, даже при наличии вертикальной или горизонтальной прокрутки страницы.
Информация изложенная здесь устарела!
Обновленный, доработанный и улучшенный вариант простой всплывающей подсказки выложен в новой статье - Универсальная всплывающая подсказка.
Текст подсказки берется из тега TITLE или из блока, расположенного рядом, в котором прописывается подсказка. Оформление и варианты положений задаются в стилях, кстати, для любителей "только на CSS" возможно использовать подсказку и без скрипта. Данный вариант в любом случаи, как мне кажется, лучше предыдущего. Обновленный, доработанный и улучшенный вариант простой всплывающей подсказки выложен в новой статье - Универсальная всплывающая подсказка.
Итак, для начала смотрим демо:
DEMO
Кто в курсе дела и сам разберется - архив с исходником и необходимыми дополнениями в конце статьи :)
Цвет, фона и текста подсказки определяется в CSS. На демонстрационной странице он черный просто для контраста.
Теперь разберемся что к чему.CSS для всплывающей подсказки
Стиль не большой и простой, но при желании можно расширить..tip {
display: inline-block;
position: relative;
}
/*Стиль для кнопки, если она есть*/
.tip em,
.linktip em {
background:#FD6E00;
text-align:center;
border-radius: 20px;
border: 1px solid #ccc;
color: #fff;
font: normal bold 12px Arial;
text-decoration: none;
cursor:pointer;
padding: 0 4px;
}
/*Стиль для изображения в подсказке*/
.tip>span>img {
max-width: 50%;
max-height: auto;
margin: 3px;
float: left;
}
/*Стиль для кнопки закрытия подсказки(кристик)*/
.answer>b,
.answer-left>b {
position:absolute;
font: normal bold 14px Comic Sans MS;
color:#999;
cursor:pointer;
padding: 4px;
}
.answer>b {
top:0;
right:0;
}
.answer-left>b {
top:0;
left:0;
}
.answer>b:hover,
.answer-left>b:hover {color:#000;} /*при наведении*/
/*Стиль для блока подсказки*/
.answer,
.answer-left {
display:none; /*скрываем*/
position:absolute; /*позиционируем абсолютно*/
z-index:9999; /*отображаем поверх всех элементов на странице*/
background: #EDEDED; /*цвет фона*/
border-radius: 3px;
border: 1px solid #ccc;
color: #000; /*цвет текста*/
font: normal 500 14px Trebuchet MS;
text-align:left;
text-shadow: 0 1px 2px #fff, 0 0 10px #E0F1FF; /*тень текста*/
text-decoration: none;
opacity: 1; /*прозрачность*/
cursor:default;
margin-top:-30px; /*смещение вверх*/
width: 200px; /*ширина !значение*/
min-height: 50px; /*минимальная высота (если текста мало)*/
max-height: auto; /*высота в зависимости от количества текста*/
white-space: normal; /*переносы слов*/
}
.answer {
box-shadow: 5px 5px 0.5em -0.1em rgba(0,0,6,0.5); /*тень справа*/
right: -240px; /*!смещение = ширина + отступы*/
padding: 5px 20px 7px 7px; /*отступы внутри*/
}
.answer-left {
box-shadow: -5px 5px 0.5em -0.1em rgba(0,0,6,0.5); /*тень слева*/
left: -240px; /*!смещение*/
padding: 5px 7px 7px 20px;
}
.a-top {
bottom: -10px; /*!смещение, положение подсказки вверх */
}
/*Стили для уголка*/
.a-top:before,
.answer:before,
.answer-left:before {
content:"";
position:absolute;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAQAAACR313BAAAAaElEQVR4XoWQMQ6AMAwDna6wMXTjB/x/7E4i9SV9AwgxuJKDcKfqrlVizInrObwLHLng9sKhgm8nIQV4eWAFJig/EIogUATCTPh7zZUUuqHXOL4m7waglViyvVthNXvaGhNr2jnTLQTenE8VKUp0n4sAAAAASUVORK5CYII=) no-repeat;
width: 9px;
height: 15px;
}
.answer:before {
left: -9px;
margin-top: 10px;
background-position: 0 0;
}
.answer-left:before {
right: -9px;
margin-top: 10px;
background-position: -9px 0;
}
.a-top:before {
bottom: 10px;
}
/*Для отображения клик-подсказки без скрипта, только на CSS*/
.tip>a:focus~span.answer,
.tip>a:focus~span.answer-left {
display:block;
}
.tip>a[tabindex="1"]:focus {
outline: none;
}
.tip>a[tabindex="1"]:focus>em {
background:#FF4F19;
}
display: inline-block;
position: relative;
}
/*Стиль для кнопки, если она есть*/
.tip em,
.linktip em {
background:#FD6E00;
text-align:center;
border-radius: 20px;
border: 1px solid #ccc;
color: #fff;
font: normal bold 12px Arial;
text-decoration: none;
cursor:pointer;
padding: 0 4px;
}
/*Стиль для изображения в подсказке*/
.tip>span>img {
max-width: 50%;
max-height: auto;
margin: 3px;
float: left;
}
/*Стиль для кнопки закрытия подсказки(кристик)*/
.answer>b,
.answer-left>b {
position:absolute;
font: normal bold 14px Comic Sans MS;
color:#999;
cursor:pointer;
padding: 4px;
}
.answer>b {
top:0;
right:0;
}
.answer-left>b {
top:0;
left:0;
}
.answer>b:hover,
.answer-left>b:hover {color:#000;} /*при наведении*/
/*Стиль для блока подсказки*/
.answer,
.answer-left {
display:none; /*скрываем*/
position:absolute; /*позиционируем абсолютно*/
z-index:9999; /*отображаем поверх всех элементов на странице*/
background: #EDEDED; /*цвет фона*/
border-radius: 3px;
border: 1px solid #ccc;
color: #000; /*цвет текста*/
font: normal 500 14px Trebuchet MS;
text-align:left;
text-shadow: 0 1px 2px #fff, 0 0 10px #E0F1FF; /*тень текста*/
text-decoration: none;
opacity: 1; /*прозрачность*/
cursor:default;
margin-top:-30px; /*смещение вверх*/
width: 200px; /*ширина !значение*/
min-height: 50px; /*минимальная высота (если текста мало)*/
max-height: auto; /*высота в зависимости от количества текста*/
white-space: normal; /*переносы слов*/
}
.answer {
box-shadow: 5px 5px 0.5em -0.1em rgba(0,0,6,0.5); /*тень справа*/
right: -240px; /*!смещение = ширина + отступы*/
padding: 5px 20px 7px 7px; /*отступы внутри*/
}
.answer-left {
box-shadow: -5px 5px 0.5em -0.1em rgba(0,0,6,0.5); /*тень слева*/
left: -240px; /*!смещение*/
padding: 5px 7px 7px 20px;
}
.a-top {
bottom: -10px; /*!смещение, положение подсказки вверх */
}
/*Стили для уголка*/
.a-top:before,
.answer:before,
.answer-left:before {
content:"";
position:absolute;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAQAAACR313BAAAAaElEQVR4XoWQMQ6AMAwDna6wMXTjB/x/7E4i9SV9AwgxuJKDcKfqrlVizInrObwLHLng9sKhgm8nIQV4eWAFJig/EIogUATCTPh7zZUUuqHXOL4m7waglViyvVthNXvaGhNr2jnTLQTenE8VKUp0n4sAAAAASUVORK5CYII=) no-repeat;
width: 9px;
height: 15px;
}
.answer:before {
left: -9px;
margin-top: 10px;
background-position: 0 0;
}
.answer-left:before {
right: -9px;
margin-top: 10px;
background-position: -9px 0;
}
.a-top:before {
bottom: 10px;
}
/*Для отображения клик-подсказки без скрипта, только на CSS*/
.tip>a:focus~span.answer,
.tip>a:focus~span.answer-left {
display:block;
}
.tip>a[tabindex="1"]:focus {
outline: none;
}
.tip>a[tabindex="1"]:focus>em {
background:#FF4F19;
}
HTML разметка
Тут доступно 2 варианта.1.Простой - добавляем к ссылке класс, по которому скрипт определит что это будет ссылка с подсказкой. Текст добавляется в атрибут TITLE.
<a class="linktip" href="#" title="Текст подсказки">SomeLink</a>
Класс .linktip говорит о том что для этой ссылки будет "построен" блок с подсказкой.2. Всплывающая подсказка с ссылками и картинками - весь блок пишется вручную. Плюс в том что такая всплывающая подсказка будет работать без скрипта, только на CSS.
<span class='tip'><a tabindex="1"><em>?</em></a><span class='answer'>Текст подсказки</span></span>
При использовании без скрипта, чтобы подсказка отображалась при наведении курсора в стилях меняем :focus на :hover
Тег <em> выполняет роль кнопки, если его нет, ссылка отображается обычно. Для скрипта, он также является фильтром отображения подсказки - при наведении курсора или по клику.jQuery скрипт для всплывающей подсказки
Скрипт самый простой. Именно он добавляет нужные классы, для правильного позиционирования(отображения) подсказки на экране и определяет способ ее появления.$(function() {
$('a.linktip').wrap('<span class="tip" />'); //оборачиваем соответствующие элементы в контейнер
$('span.tip').each(function(){
myTip = $(this),
tipLink = myTip.children('a'),
tBlock = myTip.children('span').length, //подсчитываем дочерние SPAN элементы внутри контейнера
tTitle = tipLink.attr('title') != 0, //определяем наличие тега TITLE
tipText = tipLink.attr('title'); //берем текст из тега TITLE
tipLink.removeAttr("title"); //скрываем обычный TITLE
//условие - если внутри нет доч. SPAN и есть TITLE,
//добавляем соответствующий SPAN с текстом взятым из TITLE
if(tBlock === 0 && tTitle === true){myTip.append('<span class="answer">' + tipText + '</span>')};
var tip = myTip.find('span.answer , span.answer-left').hide(); //найдем и скроем блоки с подсказками
//при наличии у ссылки тега EM подсказка будет появляется по клику
//также сразу добавим и "крестик" закрытия
tipLink.has('em').click(showTip).siblings('span').append('<b class="close">X</b>');
//если тага EM нет, подсказка будет появляться при наведении курсора
tipLink.not($('em').parent()).hoverIntent(
showTip,
function(){
tip.fadeOut(200);}
);
//закрытие подсказки при клике на "крестик"
tip.on('click', '.close', function(){
tip.fadeOut(200);}
);
//функция вывода и появления подсказки на экран
//вне зависимости от размеров окна,
//наличия горизонтальной или вертикальной прокрутки
//подсказка всегда будет в видимой области
function showTip(e){
xM = e.pageX,
yM = e.pageY,
tipW = tip.width(),
tipH = tip.height(),
winW = $(window).width(),
winH = $(window).height(),
scrollwinH = $(window).scrollTop(),
scrollwinW = $(window).scrollLeft(),
curwinH = $(window).scrollTop() + $(window).height();
if ( xM > scrollwinW + tipW * 2 ) {tip.removeClass('answer').addClass('answer-left');}
else {tip.removeClass('answer-left').addClass('answer');}
if ( yM > scrollwinH + tipH && yM > curwinH / 2 ) {tip.addClass('a-top');}
else {tip.removeClass('a-top');}
tip.fadeIn(100).css('display','block');
e.preventDefault();
};
});
});/*конец*/
$('a.linktip').wrap('<span class="tip" />'); //оборачиваем соответствующие элементы в контейнер
$('span.tip').each(function(){
myTip = $(this),
tipLink = myTip.children('a'),
tBlock = myTip.children('span').length, //подсчитываем дочерние SPAN элементы внутри контейнера
tTitle = tipLink.attr('title') != 0, //определяем наличие тега TITLE
tipText = tipLink.attr('title'); //берем текст из тега TITLE
tipLink.removeAttr("title"); //скрываем обычный TITLE
//условие - если внутри нет доч. SPAN и есть TITLE,
//добавляем соответствующий SPAN с текстом взятым из TITLE
if(tBlock === 0 && tTitle === true){myTip.append('<span class="answer">' + tipText + '</span>')};
var tip = myTip.find('span.answer , span.answer-left').hide(); //найдем и скроем блоки с подсказками
//при наличии у ссылки тега EM подсказка будет появляется по клику
//также сразу добавим и "крестик" закрытия
tipLink.has('em').click(showTip).siblings('span').append('<b class="close">X</b>');
//если тага EM нет, подсказка будет появляться при наведении курсора
tipLink.not($('em').parent()).hoverIntent(
showTip,
function(){
tip.fadeOut(200);}
);
//закрытие подсказки при клике на "крестик"
tip.on('click', '.close', function(){
tip.fadeOut(200);}
);
//функция вывода и появления подсказки на экран
//вне зависимости от размеров окна,
//наличия горизонтальной или вертикальной прокрутки
//подсказка всегда будет в видимой области
function showTip(e){
xM = e.pageX,
yM = e.pageY,
tipW = tip.width(),
tipH = tip.height(),
winW = $(window).width(),
winH = $(window).height(),
scrollwinH = $(window).scrollTop(),
scrollwinW = $(window).scrollLeft(),
curwinH = $(window).scrollTop() + $(window).height();
if ( xM > scrollwinW + tipW * 2 ) {tip.removeClass('answer').addClass('answer-left');}
else {tip.removeClass('answer-left').addClass('answer');}
if ( yM > scrollwinH + tipH && yM > curwinH / 2 ) {tip.addClass('a-top');}
else {tip.removeClass('a-top');}
tip.fadeIn(100).css('display','block');
e.preventDefault();
};
});
});/*конец*/
Однако, дабы избавится от, так называемой, "свистопляски" при быстром и многократном наведении курсора на ссылку со всплывающей подсказкой, и не мучать мозг с setTimout и setInterval, добавим один очень чудесный плагин, который я не так давно нашел в сети. Называется он hoverInternet, он уже используется в демо и добавлен в архив с исходником.
Официальная страница плагина
Вот и все, мнения, пожелания, критика - в комментах.
Скачать исходник со всеми необходимыми дополнениями, как всегда, можно из сферы, нажав на кнопку ниже. Файл - SimpleTip
СКАЧАТЬ ZIP
P.S. Отдельное спасибо классным пацанам с CyberForum.ru, которые помогли разобраться с важным моментом :).
©http://magentawave.com
Изящно! Спасибо!
ОтветитьУдалитьСтарам-с :)
УдалитьА, как сделать свою картинку для этой кнопки?? Второй день уже туплю...
ОтветитьУдалитьКакой кнопки? Со знаком вопроса? Это не картинка, это все через стили сделано, но впрочем можно и через картинку. Стиля для неё записаны в коде CSS после комментария
Удалить/*Стиль для кнопки, если она есть*/
Ну, она не отображается... я прописываю картинку , убираю радиус, и т.д. нО ЗНАЧЕК ВОПРОСА ОСТАЕТСЯ НЕИЗМЕННЫМ. Просто за ним меняется фон, на фон картинки. Я так понимаю у вас меня выполненно имено при помощи "hoverInternet" ?
УдалитьhoverInternet - это jQuery плагин, чтобы при наведении убрать зацикливание и автоматом выставить короткий таймаут на появление подсказки. Но его можно убрать и вместо функции в скрипте .hoverIntent использовать обычную функцию - .hover при этом в строке:
Удалитьtip.fadeIn(100).css('display','block');
нужно добавить функцию .stop() и будет так:
tip.stop().fadeIn(100).css('display','block');
Это я просто так изначально написал скрипт, так сказать пробовал, пожалуй обновлю пост и уберу этот плагин, можно обойтись и без него.
Что касается вашей картинки. во-первых, к скрипту это дело не имеет никакого отношения, это CSS. Во-вторых, понятное дело что знак вопроса никуда не денется ибо картинку вы подкладываете как фон, а "?" это текст, не пишите его в HTML коде для подсказки и его не будет или сделайте текст прозрачным, а размер шрифта нулевым. И не забывайте указывать в стилях для EM высоту и ширину соответствующую вашей картинке. А именно:
/*Стиль для кнопки, если она есть*/
.tip em,
.linktip em {
background:url(.../your-img-16x16.png) no-repeat;
color: transparent; /*цвет текста прозрачный*/
font: normal normal 0 Arial; /*размер шрифта - 0*/
text-decoration: none;
cursor:pointer;
height: 16px;
width: 16px;
}
Понятно что это css, но моя картинка с размерами 200/100px , с казанной даже таким образом -"min-height: 100px;" она не отображается этим размером. Чем еще может быть это ограничено?
УдалитьЯ уж теперь вообще смутно понимаю что вы творите... Код всего что вы уже сделали сюда - http://jsfiddle.net, ссылку в комент. (КОД В КОММЕНТАРИЙ НЕ ПОСТИТЬ)
Удалитьhttp://jsfiddle.net/cCZVG/
ОтветитьУдалитьhttp://jsfiddle.net/cCZVG/1/
УдалитьБольшое спасибо) Остался последний вопрос, чем регулируется ее позиционирование относительно моей картинки? Если ем же css? то сам просто позже проэкспериментирую. Еще раз спасибо!
УдалитьПодскажите по какой причине вместо подсказок может вылетать "Undefined" ? подключил вроде все правильно, окошко с подсказкой вылетает, а вместо подсказки Undefined ((
ОтветитьУдалитьВы где-то допустили ошибку в коде, такой ответ означает что содержимое не найдено, т.е. скрипт не находит блок текста подсказки. Я еще раз проверил код из статьи, все работает. Ищите ошибку у себя в коде, возможно где-то название класса спутали.
Удалитьсильно хитрый цсс
ОтветитьУдалить.tip>span>img оно может работать и так .tip span img?
.tip>a:focus~span.answer - что делает тильда?
.tip>a:focus~span.answer-left
.tip>a[tabindex="1"]:focus - а это вообще как - что это за индекс и для чего нужен?
Так сделано чтобы подсказка работала без скрипта. Чтобы было понятнее по коду и селекторам, изучаем:
Удалитьhttp://www.w3.org/TR/selectors/#selectors
http://htmlbook.ru/samcss/selektory-atributov
tabindex - указывает на приоритет подсветки ссылки при переключении клавиатурой. В данном случаи это трюк, используется чтобы убрать подсветку по умолчанию и иметь возможность дополнительно выделить значок с "?" когда подсказка активна.
tipLink.not($('em').parent()).hoverIntent( лишняя закрывающая скобка.
ОтветитьУдалитьНе работает в ие7, ни с jq ни css
Не уверен что она(скобка) лишняя, в IE7 тестил - все работает
УдалитьКлассный скрипт, спасибо. Для будущих поколений: чтобы прикрутить его к CMS Drupal, нужно исправить первую и последнюю строки.
ОтветитьУдалитьjQuery(document).ready(function($) {
...
})(jQuery);
Однако, почему-то не закрывается подсказка при клике на крестик... Помогите, пожалуйста.
УдалитьПоказывайте пример.У меня все работает.
УдалитьСпасибо за всплывающие окошечки. :)
ОтветитьУдалитьПравда не использую их по полной, просто срочно нужно было какое-то готовое решение. Пришлось убрать стрелочку блока (она классная, но не было времени делать новую картинку другого цвета). К тому же не разобрался, как увеличить ширину всплывающей подсказки.
У себя также добавил скрытие окошка по клику мимо него (кроме крестика):
$(document).click(function(event) {
if ($(event.target).closest(".tip").length) return;
$(".answer").hide();
event.stopPropagation();
});
Можно делать проще:
Удалить$('html,body').click(function(){
$(".answer").hide();
});
Как сделать закрытие подсказки не по кресту , а по клику в любое место. В демо такого нет.
ОтветитьУдалитьЗато есть в комментариях. И кстати, сказать это устаревший вариант и в скором времени будет обновлен, на более удобный и простой.
УдалитьСпасибо! То что искал
ОтветитьУдалитьЗдравствуйте, у меня подсказка установлена в ячейке таблицы и обрезается границами этой самой ячейки. Как вынести ее поверх всего?
ОтветитьУдалитьРешение казалось изящным, пока не выяснилось, что без плагина "hoverInternet" всё это "изящество" просто не работает. Жаль...
ОтветитьУдалитьИ без этого плагина все работает - http://cssdeck.com/labs/full/kh87bq0r
УдалитьСтатья написана довольно давно и данная версия подсказки уже устарела в ближайшее время будет выложен более функциональный и универсальный вариант подсказки.
Уважаемый автор, скажите как сделать что бы в вашем примере можно было выделить текст заключенный в подсказке? В данном примере при наведении курсором на подсказку она исчезает, что нужно отредактировать что бы она не исчезала и можно было выделить заключенный в нее текст?
ОтветитьУдалитьЗдравствуйте, уважаемый автор! Мне статья очень понравилась, но на нее наткнулся в поиске на вашем сайте статьи о том, как можно сделать, чтобы описание к фото, которое делается обычно при создании статьи в блоге, не было видно сразу, а появлялось при наведении мышью на фото. То есть, с hover effectом. Как это можно реализовать?
ОтветитьУдалить