简体   繁体   中英

Bootstrap Tooltips with different styles

I have tooltips showing using data-toggle like in,

 <i class="fa fa-fire fa-lg" data-toggle="tooltip" data-placement="bottom" title="Fire Place"></i>

I have styled the tooltips here using,

.tooltip > .tooltip-inner {

padding: 15px;
font-size: 120%;
background-color: #FFEB6C;
color: #374D40;}

I'd like tooltips on different places to look differentlylike the background color. ie I want multiple looks for tooltips. but I don't see how I can set custom tooltip styles to each tooltip. I can't set a css class to each tooltip either since there's no such element,I'm setting tooltips through data-toggle.

Is there any way I can make this work? Thanks.

Simple, I created a class to hold those CSS style called custom-tooltip :

/* Tooltip */

.custom-tooltip+.tooltip>.tooltip-inner {
  padding: 15px;
  font-size: 1.2em;
  background-color: #FFEB6C;
  color: #374D40;
}


/* Tooltip on bottom */

.custom-tooltip+.tooltip.bottom>.tooltip-arrow {
  border-bottom: 5px solid #FFEB6C;
}

 $('i[data-toggle="tooltip"]').tooltip({ animated: 'fade', placement: 'bottom' }); 
 /* Tooltip */ .custom-tooltip+.tooltip>.tooltip-inner { padding: 15px; font-size: 1.2em; background-color: #FFEB6C; color: #374D40; } /* Tooltip on top */ .custom-tooltip+.tooltip.top>.tooltip-arrow { border-top: 5px solid #FFEB6C; } /* Tooltip on bottom */ .custom-tooltip+.tooltip.bottom>.tooltip-arrow { border-bottom: 5px solid #FFEB6C; } /* Tooltip on left */ .custom-tooltip+.tooltip.left>.tooltip-arrow { border-left: 5px solid #FFEB6C; } /* Tooltip on right */ .custom-tooltip+.tooltip.right>.tooltip-arrow { border-right: 5px solid #FFEB6C; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" /> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" /> <i class="fa fa-fire fa-lg custom-tooltip" data-toggle="tooltip" data-placement="bottom" title="Fire Place"></i> 

I have prepared a quite universal solution for the bootstrap 3 tooltips' styling working with the dynamically created elements. It will work also in a case when a tooltip is generated not as a sibling to its element, but on a higher level of DOM, for example when a custom container option has been used:

<body>
    <div>
    <button type="button" class="btn btn-default" data-container="body" title="Tooltip text">Hover over me</button>
    </div>
</body>

The tooltip's <div> will be generated there as a sibling to <div> , instead of <button> ...

Solution

Let's make the template option of the Bootstrap tooltip object dynamic:

$.fn.tooltip.Constructor.prototype.tip = function () {
    var template;
    var $e = this.$element;
    var o  = this.options;
    if (!this.$tip) {
        template = typeof o.template == 'function' ? o.template.call($e[0]) :  o.template;
        this.$tip = $(template);
        if (this.$tip.length != 1) {
            throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!');
        }
    }
    return this.$tip;
}

Prepare the tooltip template function. It will get all "tooltip-*" classes from the element with tooltip and append to the "tooltip-arrow" and "tooltip-inner" divs

tooltipTemplate = function () {
    var classList = ($(this).attr('class')||"").split(/\s+/);
    var filterTooltipPrefix = function(val){
        return val.startsWith('tooltip-');
    };
    var tooltipClasses = classList.filter(filterTooltipPrefix).join(' ');
    return '<div class="tooltip" role="tooltip"><div class="tooltip-arrow ' + tooltipClasses +'"></div><div class="tooltip-inner ' + tooltipClasses +'"></div></div>';
}

Ensure our function works in older browsers:

if (!String.prototype.startsWith) {
    String.prototype.startsWith = function(searchString, position){
        position = position || 0;
        return this.substr(position, searchString.length) === searchString;
    };
}

Now enable the tooltips:

$('body').tooltip({ 
    selector: "[title]", 
    html: true,
    template: tooltipTemplate
});

Example:

HTML

<h1>Test tooltip styling</h1>
<div><span title="Long-long-long tooltip doesn't fit the single line">Hover over me 1</span></div>
<div><span class="tooltip-left" data-container="body" title="Example (left aligned):<br>Tooltip doesn't fit the single line, and is not a sibling">Hover over me 2</span></div>
<div><span class="tooltip-large tooltip-left" title="Example (left aligned):<br>This long text we want to have in the single line">Hover over me 3</span></div>

CSS

.tooltip-inner.tooltip-large {
    max-width: 300px;
}

.tooltip-inner.tooltip-left {
    text-align: left;
}

Here is working demo: https://www.bootply.com/Mz48qBWXFu

Note I was not able to run this code on jsfiddle, which uses Bootstrap 4. It throws an error: TOOLTIP: Option "template" provided type "function" but expected type "string"
Apparently some additional tweaking is necessary there.


UPDATE

Everything above was an overkill in 2 places:

Instead of posting the tooltip styling classes in the class property of an element, it is better to use a data- property. That would simplify the tooltipTemplate function and remove the startsWith code shim:

tooltipTemplate = function () {
    var tooltipClasses = $(this).data('tooltip-custom-classes');
    return '<div class="tooltip" role="tooltip"><div class="tooltip-arrow ' + tooltipClasses +'"></div><div class="tooltip-inner ' + tooltipClasses +'"></div></div>';
}

Much more important, we don't need to modify tooltip template at all. We should have a callback to the inserted.bs.tooltip event. That would simplify everything (thanks go to Oleg for his answer https://stackoverflow.com/a/42994192/9921853 ):

Bootstrap 3:

$(document).on('inserted.bs.tooltip', function(e) {
    var tooltip = $(e.target).data('bs.tooltip');
    tooltip.$tip.addClass($(e.target).data('tooltip-custom-class'));
});

Bootstrap 4:

$(document).on('inserted.bs.tooltip', function(e) {
    var tooltip = $(e.target).data('bs.tooltip');
    $(tooltip.tip).addClass($(e.target).data('tooltip-custom-class'));
});

Here are the whole examples:
for Bootstrap 3
for Bootstrap 4

try this

<i id="my-tooltip-1" class="fa fa-fire fa-lg" data-toggle="tooltip" data-placement="bottom" title="Fire Place"></i>

<style>
#my-tooltip-1 + .tooltip > .tooltip-inner {
        padding: 15px;
        font-size: 120%;
        background-color: #FFEB6C;
        color: #374D40;

        /* do something */
}
#my-tooltip-1 + .tooltip > .tooltip-arrow {
        background-color: #FFEB6C;

        /* do something */
}
</style>

I too have been searching (far and wide) for an answer to apply different styles to selective tooltips in Bootsrap 4 and to say I was getting frustrated is an understatement.

Lots of threads simply address styling global .tooltip-inner or using scripting to accomplish this, even Bootstrap probably should have provided a simpler way.

Anyhow here's my own personal scenario & workaround.

I generally stick to the basic Bootstrap tooltip options ( I assume this is working already , otherwise see update below) for various tooltips appearing on pages, but on my Navbar I have a keyboard shortcut Favicon in an anchor tag which I wanted to style. The way I accomplished this is by wrapping it in a span tag (or "data-container" as George put it [see credits]).

<link href='https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css' rel='stylesheet'/>
<link href='https://use.fontawesome.com/releases/v5.6.3/css/all.css' rel='stylesheet'/>

<script src='https://code.jquery.com/jquery-3.3.1.slim.min.js'/>
<script src='https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js'/>
<script src='https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js'/>

<nav>
...
<span class="tt_kb">
<a class="nav-item nav-link px-2" href="#" data-toggle="tooltip"  placement="auto"  data-html="true" container="body" trigger="hover" data-container=".tt_kb" data-boundary="window" title="Keyboard Shortcuts ... blah blah blah"><i class="far fa-keyboard"></i></a>
</span>
...
</nav>

<style>
.tt_kb .tooltip .tooltip-inner {
    background-color: #3266FF;
    text-align: left;
    width: 200px;
    position: relative;
    right: 50px;
}
</style>

The odd thing for me is that for some reason the [ position="auto" ] didn't work (well) as I have the tt_kb Favicon on the top right hand side of the Navbar, half of the tooltip was disappearing outside my window , hence I added [ position:relative & right:50px ] in the CSS to get around this. Overall this worked reasonably well for me and I suppose with a little tweaking you could get this to work in your scenario.

Hope this help )


credits : Idea came from George 's " Using a custom style for each tooltip " commnent on thread stackoverflow/questions/re-color-tooltip-in-bootstrap-4 which sadly I could not even mark as useful of comment on due to me being new without reputation (


UPDATE

For those who don't have the general Bootstrap/Popper tooltips working you may want to add the following script & general styles to your code.

  <script> $(document).ready(function(){ $('[data-toggle="tooltip"]').tooltip(); }); $('[data-toggle="tooltip"]').each(function(){ var options = { html: true }; if ($(this)[0].hasAttribute('data-type')) { options['template'] = '&#60;div class="tooltip ' + $(this).attr('data-type') + '" role="tooltip"&#62;' + ' &#60;div class="tooltip-arrow"&#62;&#60;/div&#62;' + ' &#60;div class="tooltip-inner"&#62;&#60;/div&#62;' + '&#60;/div&#62;'; } $(this).tooltip(options); }); </script> </style> .tooltip.primary .tooltip-inner { background-color: #31b0d5; } .tooltip.primary.top > .tooltip-arrow { border-top-color: #337ab7; } .tooltip.primary.right > .tooltip-arrow { border-right-color: #337ab7; } .tooltip.primary.bottom > .tooltip-arrow { border-bottom-color: #337ab7; } .tooltip.primary.left > .tooltip-arrow { border-left-color: #337ab7; } .tooltip.info .tooltip-inner { background-color: #31b0d5; } .tooltip.info.top > .tooltip-arrow { border-top-color: #31b0d5; } .tooltip.info.right > .tooltip-arrow { border-right-color: #31b0d5; } .tooltip.info.bottom > .tooltip-arrow { border-bottom-color: #31b0d5; } .tooltip.info.left > .tooltip-arrow { border-left-color: #31b0d5; } .tooltip.success .tooltip-inner { background-color: #449d44; } .tooltip.success.top > .tooltip-arrow { border-top-color: #449d44; } .tooltip.success.right > .tooltip-arrow { border-right-color: #449d44; } .tooltip.success.bottom > .tooltip-arrow { border-bottom-color: #449d44; } .tooltip.success.left > .tooltip-arrow { border-left-color: #449d44; } .tooltip.warning .tooltip-inner { background-color: #ec971f; } .tooltip.warning.top > .tooltip-arrow { border-top-color: #ec971f; } .tooltip.warning.right > .tooltip-arrow { border-right-color: #ec971f; } .tooltip.warning.bottom > .tooltip-arrow { border-bottom-color: #ec971f; } .tooltip.warning.left > .tooltip-arrow { border-left-color: #ec971f; } .tooltip.danger .tooltip-inner { background-color: #d9534f; } .tooltip.danger.top > .tooltip-arrow { border-top-color: #d9534f; } .tooltip.danger.right > .tooltip-arrow { border-right-color: #d9534f; } .tooltip.danger.bottom > .tooltip-arrow { border-bottom-color: #d9534f; } .tooltip.danger.left > .tooltip-arrow { border-left-color: #d9534f; } </style> 

UPDATE

Added fully working JSFiddle Demo

NB For some reason the Navbar won't align right in the demo unless you view it zoomed at 110 % or 125 %!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM