我可以自定义浏览器内工具提示泡泡吗?

时间:2011-07-13 20:02:57

标签: html css3 browser

他们是一种自定义工具提示气泡样式的方式,跨浏览器吗?

例如,当我将鼠标悬停在具有title属性的标记上时,Firefox会显示工具提示气泡。我想将其定制为与网站的其他部分一样。

是否有CSS3入侵?如果没有,我可以用能在所有带有title属性的元素上自动工作的东西替换它吗?

<a href="" title="This is a nice link, click here"/> <div onclick="" title="A nice action button"/>

图片示例:

A nice example image of my site.

我正在努力让我的网站看起来很好看并准备好服务。我注意到的一件事是工具提示打破了我的风格,只是一点......但我对这些东西很疯狂。是的我还在努力 - http://pagelook.us。巨大的工作正在进行中。将鼠标悬停在任何导航按钮上以显示活动示例。

7 个答案:

答案 0 :(得分:6)

我只是想指出,为标题显示的工具提示通常是内置于操作系统中的工具提示,浏览器不提供CSS界面来覆盖操作系统默认值。

通常,浏览器甚至不会修改自己的外观和行为。

答案 1 :(得分:2)

CSS上没有任何内容可用于自定义工具提示。您将不得不使用Javascript或任何其他JS框架来实现它。目前,有数百种不同的jQuery和Mootools片段,您可以免费下载并根据自己的需要进行定制。

答案 2 :(得分:1)

我不知道CSS的任何浏览器扩展,可让您自定义工具提示的外观。

虽然有很多jQuery工具提示插件,例如

您可以将其应用于具有title属性的所有HTML元素,如下所示:

$("*[title]").tooltip();

(不确定它的表现如何。)

答案 3 :(得分:1)

如果您不想使用Javascript,可以使用纯CSS实现。但是可能存在一些限制。 JS工具提示可以有更多功能。

例如,请检查以下内容:

答案 4 :(得分:1)

你也可以从那个小提琴开始: http://jsfiddle.net/2RN6E/

并添加更多CSS

答案 5 :(得分:0)

当然,我为jQuery开发了这个插件,你只需要将它包含在你的页面中

以下是如何让它发挥作用:http://plugins.jquery.com/project/jTitle

/*! jQuery Tooltip Plugin by Pezhvak @ IMVx.ORG
 *  Version: 1.0
 *  Tested on IE9, FF4, Safari5
 *  Description: By using this plugin all of your title attributes going to change, you may even change your tooltips in runtime
 */

(function($){
    /*
     * @groupName: [string] name of the group of titlebox
     * @ms: [milliseconds] to hide, if 0: hide when mouseout, if -1: don't hide automatically, if -2: hide when clicked on title
     * @delay: [milliseconds] to show, -1: don't show automatically
     * @mode: [string] how you want to manage your titles, single: only one toolbox allowed to be shown in each category, share: one toolbox will be shared between all elements in a group, free: each element have it's own titlebox
     * @move: [string] how titlebox appears, vertically, horizontally or static. static: without moving effect
     * @stop: [string] which side of the element titlebox should stop? on width or height?
     * @showEasing: [string] what effect to use when titlebox appears, [easeOutBounce, easeOutElastic]
     * @hideEasing: [string] what effect to use when titlebox disappears, [same as showEasing]
     * @moveEasing: [string] what effect to use when titlebox is moving to other element, [same as showEasing], it will be used only when mode is
     * @theme: [object] contains style of the titlebox
     * ! Keep in mind you may override default settings for your special elements by setting [titleMS, titleMove, titleStop, titleShowEasing, titleHideEasing, titleTheme] attribute for them.
     * ! titleTheme should contains created theme name by $.createTheme function
     */
    var option = {groupName: '_default_', 
                  ms: 5000, 
                  speed: 'slow', 
                  delay: 0, 
                  distance: 'auto', 
                  mode: 'single', 
                  move: 'horizontally', 
                  stop: 'width', 
                  recommend: 'auto', 
                  showEasing: 'easeOutBounce', 
                  hideEasing: 'easeInOutBounce', 
                  moveEasing: 'easeOutElastic', 
                  theme:{
                      shadow: '0px 0px 5px #292929', 
                      opacity: 0.8,
                      roundCorners: 5, 
                      style: {
                          color: '#fff', 
                          background: 'rgba(0,0,0, 0.8)', 
                          padding: '10px', 
                          fontSize: '12px'
                      }
                  }
    };
    var _idc = 0; // ID Counter
    var groups = {};
    var currentGroup = {};

    $.titleDefineGroup = function(group_name, options)
    {
        var option_buffer = $.extend(true, {}, option);
        groups[group_name] = $.extend(true, option_buffer, options);
        groups[group_name].groupName = group_name;
    }

    function get_image_size(image_uri)
    {
        var image = new Image();
        image.src = image_uri;
        return {width: image.width, height: image.height};
    }

    $(window).bind('load.tooltip', function(){
        $("[title]").live('mouseover.tooltip', function(){
            _idc++;
            $(this).attr('customTitle', $(this).attr('title')).attr('title', null).attr('_idc', _idc);
            this.onTitleShow = function(){} // titleShowEvent
            this.onTitleHide = function(){} // titleHideEvent
            $(this).mouseover();
        });

        $("[customTitle]").live('mouseover.tooltip', function(){
            $(this).tooltip({text: $(this).attr("customTitle")});
        });
    });

    $.fn.onTitleShow = function(fnc)
    {
        return this.each(function(){
            this.onTitleShow = fcn;
        });
    };

    $.fn.onTitleHide = function(fnc)
    {
        return this.each(function(){
            this.onTitleHide = fnc;
        });
    };

    $.fn.showTitle = function()
    {
        return this.each(function(){
            if($(this).attr("customTitle")!="")
            {
                _idc++;
                $(this).attr('customTitle', $(this).attr('title')).attr('title', null).attr('_idc', _idc);
                this.onTitleShow = function(){} // titleShowEvent
                this.onTitleHide = function(){} // titleHideEvent
                $(this).tooltip({text: $(this).attr("customTitle"), forced: true});
            }
        });
    }

    $.titleSettings = function(options)
    {
        $.extend(true, option, options);
    };

    function _tooltip_generate_arrow(side)
    {
        var canvas = document.createElement('canvas');
        if(!canvas.getContext) return;
        var canvasContext = canvas.getContext('2d');
        canvasContext.beginPath();
        switch(side)
        {
            case "up":{
                canvas.width = '8';
                canvas.height = '6';

                canvasContext.moveTo(4,0);
                canvasContext.lineTo(8,6);
                canvasContext.lineTo(0,6);
                canvasContext.lineTo(4,0);

            }break;
            case "down":{
                canvas.width = '8';
                canvas.height = '6';

                canvasContext.moveTo(4,6);
                canvasContext.lineTo(0,0);
                canvasContext.lineTo(8,0);
                canvasContext.lineTo(4,6);
            }break;
            case "left":{
                canvas.width = '6';
                canvas.height = '8';

                canvasContext.moveTo(0,4);
                canvasContext.lineTo(6,0);
                canvasContext.lineTo(6,8);
                canvasContext.lineTo(0,4);
            }break;
            case "right":{
                canvas.width = '6';
                canvas.height = '8';

                canvasContext.moveTo(6,4);
                canvasContext.lineTo(0,0);
                canvasContext.lineTo(0,8);
                canvasContext.lineTo(6,4);
            }break;
        }

        canvasContext.fillStyle = currentGroup.theme.style.background;
        canvasContext.fill();
        canvas.style.position = 'absolute';
        $(canvas).fadeOut(1);
        return canvas;
    }

    function _tooltip_conflict(element, tooltip)
    {
        var result = {left: false, right: false, top: false, bottom: false, leftPoint: {x: 0, y: 0, position: 'center'}, rightPoint: {x: 0, y: 0, position: 'center'}, topPoint: {x: 0, y: 0, position: 'center'}, bottomPoint: {x: 0, y: 0, position: 'center'}};
        var elementPosition = element.offset();
        var padding = parseInt(tooltip.css('padding').replace('px','')) * 2;
        if(isNaN(padding)) padding = 0;
        var tooltipWidth = tooltip.width() + padding;
        var tooltipHeight = tooltip.height() + padding;
        var arrow = '';

        // Checking left
        arrow = _tooltip_generate_arrow('right');
        if(elementPosition.left - tooltipWidth - arrow.width < 0) result.left = true;
        else{
            result.leftPoint.x = elementPosition.left - tooltipWidth - arrow.width;
            result.leftPoint.y = (tooltipHeight > element.height()) ? elementPosition.top - (tooltipHeight/2) + (element.height()/2) : elementPosition.top + (element.height()/2) - (tooltipHeight/2);
            if(result.leftPoint.y < 0) {result.leftPoint.y = elementPosition.top; result.leftPoint.position = 'top';}
            if(result.leftPoint.y + tooltipHeight > $(window).height()) {result.leftPoint.y = elementPosition.top - (tooltipHeight - element.height()); result.leftPoint.position = 'bottom';}
        }
        // Checking Right
        arrow = _tooltip_generate_arrow('left');
        if(elementPosition.left + element.width() + tooltipWidth + arrow.width > $(window).width()) result.right = true;
        else{
            result.rightPoint.x = elementPosition.left + element.width() + arrow.width;
            result.rightPoint.y = (tooltipHeight > element.height()) ? elementPosition.top - (tooltipHeight/2) + (element.height()/2) : elementPosition.top + (element.height()/2) - (tooltipHeight/2);
            if(result.rightPoint.y < 0) {result.rightPoint.y = elementPosition.top; result.rightPoint.position = 'top';}
            if(result.rightPoint.y > $(window).height()) {result.rightPoint.y = elementPosition.top - (tooltipHeight - element.height()); result.rightPoint.position = 'bottom';}
        }
        // Checking Up
        arrow = _tooltip_generate_arrow('down');
        if(elementPosition.top - tooltipHeight - arrow.height < 0) result.top = true;
        else{
            result.topPoint.x = (tooltipWidth > element.width()) ? elementPosition.left - (tooltipWidth/2) + (element.width()/2) : elementPosition.left + (element.width()/2) - (tooltipWidth/2);
            result.topPoint.y = elementPosition.top - tooltipHeight - arrow.height;
            if(result.topPoint.x < 0) {result.topPoint.x = elementPosition.left; result.topPoint.position = 'left';}
            if(result.topPoint.x+tooltipWidth > $(window).width()) {result.topPoint.x = elementPosition.left - (tooltipWidth - element.width()); result.topPoint.position = 'right';}
        }
        // Checking Down
        arrow = _tooltip_generate_arrow('up');
        if(elementPosition.top + element.height() + tooltipHeight + arrow.height > $(window).height()) result.bottom = true;
        else{
            result.bottomPoint.x = (tooltipWidth > element.width()) ? elementPosition.left - (tooltipWidth/2) + (element.width()/2) : elementPosition.left + (element.width()/2) - (tooltipWidth/2);
            result.bottomPoint.y = elementPosition.top + element.height() + arrow.height;
            if(result.bottomPoint.x < 0) {result.bottomPoint.x = elementPosition.left; result.bottomPoint.position = 'left';}
            if(result.bottomPoint.x+tooltipWidth > $(window).width()) {result.bottomPoint.x = elementPosition.left - (tooltipWidth - element.width()); result.bottomPoint.position = 'right';}
        }

        return result;
    }

    function _tooltip_get_box_position()
    {

    }

    $.tooltip_proccess = function(){
        // Define
        $("[title]:not([titleGroup])").attr("titleGroup", "_default_");
        var settings = {move: 0, stop: 0, mode: 'single', recommend: 'auto', group: 'default', startPoint: {x: 0, y: 0}, endPoint: {x: 0, y: 0}}
        settings.group = (($(this).attr("titleGroup")) ? (groups[$(this).attr("titleGroup")]) ? groups[$(this).attr("titleGroup")] : option : option);
        currentGroup = settings.group;
        settings.move = (($(this).attr("titleMove")) ? $(this).attr("titleMove") : settings.group.move).toLowerCase();
        settings.stop = (($(this).attr("titleStop")) ? $(this).attr("titleStop") : settings.group.stop).toLowerCase();
        settings.recommend = (($(this).attr("titleRecommend")) ? $(this).attr("titleRecommend") : settings.group.recommend).toLowerCase();

        // Verifying
        if($(this).attr("titleActive")=="true") return; // prevent re-generation for elements which already have an active toolbox

        if(settings.group.mode != 'free')
        {
            var force_return = false;
            $("[titleGroup='"+$(this).attr("titleGroup")+"'][titleActive='true']").each(function(){
                clearTimeout(document.getElementById("toolbox_"+this.id).tooltipTimeout); // prepair to move
                clearInterval(this.onTitleChange);
                $("#toolbox_"+this.id).attr("titleActive", "false");
                if(settings.group.mode == 'single')
                {
                    this.hideTitle();
                }
                else // share
                {
                    force_return = true; // we goint to handle it from here, we don't need rest of the code ;)
                    var elementPos = $(this).offset();
                    var conflict = _tooltip_conflict($(this), $("#toolbox_"+this.id)); 
                    var padding = parseInt(($("#toolbox_"+this.id).css("padding")).replace("px", ""));
                    var DIV = document.getElementById("toolbox_"+this.id);

                    //end
                }
            });
            if(force_return) return;
        }

        // Generating TooltipBox
        $(this).attr("titleActive", "true");
        _idc++;
        var DIV = document.createElement("DIV");
        if($(this).attr("id") == "") $(this).attr("id", "auto_"+_idc);
        DIV.name = DIV.id = "toolbox_"+$(this).attr("id");
        DIV.style.position = 'absolute';
        $.extend(true, DIV.style, settings.group.theme.style);
        DIV.style.background = settings.group.theme.style.background;

        DIV.style.zIndex = 999;
        DIV.innerHTML = $(this).attr("customTitle");
        this.onTitleChange = setInterval(function(){
            if($(_this).attr("customTitle") != DIV.childNodes[0].nodeValue) DIV.childNodes[0].nodeValue = $(_this).attr("customTitle");
        }, 100);

        DIV.style.width = 'auto';
        DIV.style.height = 'auto';
        DIV.style.whiteSpace = 'nowrap';

        DIV.style['-moz-box-shadow'] = settings.group.theme.shadow;
        DIV.style['-webkit-box-shadow'] = settings.group.theme.shadow;
        DIV.style['box-shadow'] = settings.group.theme.shadow;



        if(typeof(settings.group.theme.roundCorners) != 'number') settings.group.theme.roundCorners = settings.group.theme.roundCorners.replace(/px$/i, '');
        $(DIV).fadeTo(1,1).attr('_tidc', $(this).attr('_idc')).roundCorners(settings.group.theme.roundCorners);
        document.body.appendChild(DIV);

        // Determining

        var elementPos = $(this).offset();
        var conflict = _tooltip_conflict($(this), $(DIV)); 
        var padding = parseInt(($(DIV).css("padding")).replace("px", ""));

        // Adjusting Box
        switch(settings.stop)
        {
            case "width":
            {
                switch(settings.recommend)
                {
                    case "up":
                    case "top":
                    {
                        if(conflict.top) settings.recommend = 'bottom';
                    }break;
                    case "down":
                    case "bottom":
                    {
                        if(conflict.bottom) settings.recommend = 'top';
                    }break;
                    default: // Auto
                    {
                        settings.recommend = (elementPos.top < $(window).height() / 2) ? 'bottom' : 'top';
                    }break;
                }

                if(settings.move == 'vertically')
                {
                    settings.startPoint.x = conflict[settings.recommend+'Point'].x;
                    settings.startPoint.y = settings.startPoint.y = (elementPos.top < $(window).height() / 2) ? ($(window).height() / 3) * 2 : ($(window).height() / 3);
                }
                else
                {
                    settings.startPoint.x = (elementPos.left < $(window).width() / 2) ? ($(window).width() / 3) * 2 : ($(window).width() / 3);
                    settings.startPoint.y = conflict[settings.recommend+'Point'].y;
                }
                settings.endPoint.x = conflict[settings.recommend+'Point'].x;
                settings.endPoint.y = conflict[settings.recommend+'Point'].y;
            }break;
            default:
            case "height":
            {
                switch(settings.recommend)
                {
                    case "left":
                    {
                        if(conflict.left) settings.recommend = 'right';
                    }break;
                    case "right":
                    {
                        if(conflict.right) settings.recommend = 'left';
                    }break;
                    default: // Auto
                    {
                        settings.recommend = (elementPos.left < $(window).width() / 2) ? 'right' : 'left';
                    }break;
                }
                if(settings.move == 'vertically')
                {
                    settings.startPoint.x = conflict[settings.recommend+'Point'].x;
                    settings.startPoint.y = settings.startPoint.y = (settings.recommend == 'bottom') ? ($(window).height() / 3) * 2 : ($(window).height() / 3);
                }
                else
                {
                    settings.startPoint.x = (elementPos.left < $(window).width() / 2) ? ($(window).width() / 3) * 2 : ($(window).width() / 3);
                    settings.startPoint.y = conflict[settings.recommend+'Point'].y;
                }

                settings.endPoint.x = conflict[settings.recommend+'Point'].x;
                settings.endPoint.y = conflict[settings.recommend+'Point'].y;
            }break;
        }

        // Setting up distance
        if(typeof(settings.group.distance) == "string")
            settings.group.distance = settings.group.distance.replace(/px$/gi, '');

        if(settings.startPoint.x != settings.endPoint.x && settings.group.distance != 'auto') // horizontal move
        {
            var res = settings.endPoint.x - settings.startPoint.x;
            if(res < 0) // tooltip is moving to left
                settings.startPoint.x = parseInt(settings.endPoint.x) + parseInt(settings.group.distance);
            else // tooltip is moving to right
                settings.startPoint.x = parseInt(settings.endPoint.x) - parseInt(settings.group.distance);
        }

        if(settings.startPoint.y != settings.endPoint.y && settings.group.distance != 'auto') // vertical move
        {
            var res = settings.endPoint.y - settings.startPoint.y;
            if(res < 0) // tooltip is moving to top
                settings.startPoint.y = parseInt(settings.endPoint.y) + parseInt(settings.group.distance);
            else // tooltip is moving to bottom
                settings.startPoint.y = parseInt(settings.endPoint.y) - parseInt(settings.group.distance);
        }


        // Adjusting Arrow
        var arrow = '';

        switch(settings.recommend)
        {
            case "top":
            {
                arrow = _tooltip_generate_arrow("down");
                arrow.style.top = (DIV.offsetHeight-1)+"px";
                arrow.style.left = ((DIV.offsetWidth/2) - (arrow.width/2))+"px";
            }break
            case "bottom":
            {
                arrow = _tooltip_generate_arrow("up");
                arrow.style.top = "-"+arrow.height+"px";
                arrow.style.left = ((DIV.offsetWidth/2) - (arrow.width/2))+"px";
            }break
            case "left":
            {
                arrow = _tooltip_generate_arrow("right");
                arrow.style.top = ((DIV.offsetHeight / 2) - arrow.height / 2)+"px";
                arrow.style.left = (DIV.offsetWidth)+"px";
            }break
            case "right":
            {
                arrow = _tooltip_generate_arrow("left");
                arrow.style.top = ((DIV.offsetHeight / 2) - arrow.height / 2)+"px";
                arrow.style.left = "-"+arrow.width+"px";
            }break
        }
        arrow.id = "tooltip_arrow_"+$(this).attr("id");

        var position = conflict[settings.recommend+'Point'].position;
        switch(position) // by default (if no conflict happends) it will be center, usually it will change when tooltip box is grater than element in size
        {
            case "bottom":
            {
                arrow.style.top = ($(DIV).height() - ($(this).height()/2-arrow.height/2))+"px";
            }break;
            case "top":
            {
                arrow.style.top = ($(this).height()/2-arrow.height/2)+"px";
            }break;
            case "left":
            {
                arrow.style.left = ($(this).width()/2-arrow.width/2)+"px";
            }break;
            case "right":
            {
                arrow.style.left = ($(DIV).width() - ($(this).width()/2 + arrow.width/2))+"px";
            }break;
        }
        // Appending Arrow To Box
        DIV.appendChild(arrow);

        // Moving Box
        opts = $.extend({left: settings.endPoint.x, top: settings.endPoint.y}, {opacity: 1});
        var element = $(this);
        var _this = this;

        this.hideTitle = function()
        {
            opts = $.extend({left: $(DIV).attr("startX"), top: $(DIV).attr("startY")}, {opacity: 0});
            $(DIV).animate(opts, {duration: settings.group.speed, easing: settings.group.hideEasing, complete: function(){if(!isNaN(DIV)) document.body.removeChild(DIV); element.attr("titleActive", "false");}});
            this.onTitleHide.call(this);
            clearInterval(this.onTitleChange);
        }

        this.onTitleShow();
        $(DIV).css({top: settings.startPoint.y, left: settings.startPoint.x}).animate(opts,{
            duration: settings.group.speed,
            easing: settings.group.showEasing,
            complete: function(){
                $(this).attr("startX", settings.startPoint.x).attr("startY", settings.startPoint.y);
                switch(settings.group.ms.toString())
                {
                    case '0': // mouseout
                    {
                        element.bind('mouseout.tooltip', function(){
                            _this.hideTitle();
                        });
                    }break;
                    case '-1':// manual
                    {

                    }break;
                    case '-2':// manual
                    {
                        $(DIV).bind('click.tooltip', function(){
                            _this.hideTitle();
                        });
                    }break;
                    default:
                    {
                        DIV.tooltipTimeout = setTimeout(function(){
                            _this.hideTitle();
                        }, settings.group.ms);
                    }break;
                }

            }
        });
    }

    $.fn.tooltip = function(options){
        return this.each(function(){
            $(this).attr("delay", 'true').bind("mouseout.tooltip", function(){$(this).attr("delay", "false"); clearTimeout(this.delayTimeout);});
            var _this = this;
            var group = (($(this).attr("titleGroup")) ? (groups[$(this).attr("titleGroup")]) ? groups[$(this).attr("titleGroup")] : option : option);
            if(options.forced == true) $.tooltip_proccess.call(_this);
            if(group.delay == -1) return;
            _this.delayTimeout = setTimeout(function(){
                if($(_this).attr("delay") == "true")
                    $.tooltip_proccess.call(_this);
            }, group.delay);
        });
    };
})(jQuery)

答案 6 :(得分:0)

你也可以试试这个:

http://djgdesign.co.uk/display.php?id=47

这可以通过使用div并将其放在光标旁边来实现:)

相关问题