223

I need to display a tooltip on a disabled button and remove it on an enabled button. Currently, it works in reverse.

What is the best way to invert this behaviour?

$('[rel=tooltip]').tooltip();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<hr>
<button class="btn" disabled rel="tooltip" data-title="Dieser Link führt zu Google">button disabled</button>
<button class="btn" rel="tooltip" data-title="Dieser Link führt zu Google">button not disabled</button>

Here is a demo

P.S.: I want to keep the disabled attribute.

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Lorraine Bernard
  • 13,000
  • 23
  • 82
  • 134
  • the button that need to be disabled is disabled... – KoU_warch Nov 09 '12 at 16:07
  • @EH_warch I want to keep the button disabled but at the same time display a tooltip on click event. – Lorraine Bernard Nov 09 '12 at 16:12
  • 3
    This won't help the OP, but future visitors may appreciate knowing that the 'readonly' attribute is similar (though not identical) and does not block user events like mouseover. – Chuck Aug 27 '13 at 20:50

21 Answers21

315

You can wrap the disabled button and put the tooltip on the wrapper:

<div class="tooltip-wrapper" data-title="Dieser Link führt zu Google">
  <button class="btn btn-default" disabled>button disabled</button>
</div>

If the wrapper has display:inline then the tooltip doesn't seem to work. Using display:block and display:inline-block seem to work fine. It also appears to work fine with a floated wrapper.

UPDATE Here's an updated JSFiddle that works with the latest Bootstrap (3.3.6). Thanks to @JohnLehmann for suggesting pointer-events: none; for the disabled button.

http://jsfiddle.net/cSSUA/209/

balexand
  • 9,549
  • 7
  • 41
  • 36
  • 5
    This is what the docs suggest and it works if you use the inline-block trick suggested here! –  Apr 08 '14 at 18:20
  • 4
    However, if your button is part of a button group then wrapping the button throws off your aesthetics :( Anyway to overcome this issue for `btn-group`s? – Cody Nov 04 '14 at 18:31
  • 2
    Cody, for btn-groups, I found you can't wrap them, or they won't get rendered correctly. I set pointer-events to 'auto' (just targeted with: "div.btn-group > .btn.disabled { pointer-events: auto; }" just in case), and also hooked up the onclick event of the button so it just returns false. Felt hacky, but it worked for our app. – Michael Jun 22 '15 at 18:27
  • 3
    This does not seem to work in bootstrap 3.3.5. [JSFiddle](http://jsfiddle.net/o3r0b7re/) – bytesized Jul 27 '15 at 01:19
  • 21
    For bootstrap 3.3.5 also add .btn-default[disabled] { pointer-events:none; } – John Lehmann Aug 19 '15 at 16:12
  • You should update you answer with @JohnLehmann hint to keep it working with 3.3.5+ too. – Hexodus Feb 15 '16 at 21:52
  • The downside of this solution is the addition of the margin, without the margin it doesn't work:( – lcjury Feb 11 '19 at 14:20
  • Hello, I'm trying to use this to fix my issue but I don't know where this portion from the fiddle need to be set " $(function() { $('.tooltip-wrapper').tooltip({position: "bottom"}); });" Could you help me please? – Manuela CodingPadawan Feb 13 '19 at 16:29
  • 1
    @Cody You can give the wrapper (fieldset or div) the `class="btn-group"` and the aestehtics is back in business. This is tested on bs5. – Matthias Arras Apr 19 '23 at 09:07
  • Adding class="btn-group" didn't work for me in boostrap 5 for some reason, it still removes the spacing between the disabled button and the one after. However what worked for me is putting an empty or
    after the button, inside the wrapper. This seems to trick bootstrap into thinking the wrapper is a dropdown button or something similar.
    – Raj Aug 15 '23 at 23:12
131

This can be done via CSS. The "pointer-events" property is what's preventing the tooltip from appearing. You can get disabled buttons to display tooltip by overriding the "pointer-events" property set by bootstrap.

.btn.disabled {
    pointer-events: auto;
}
Gene Parcellano
  • 5,799
  • 5
  • 36
  • 43
  • Took me forever to figure out that bootstrap uses this property to turn off tooltips on disabled .btn-elements. – martin Aug 14 '14 at 18:05
  • 2
    Just a side note, this only works for IE in 11 or higher. Pretty much all other modern browsers have supported it for a while. See: http://caniuse.com/#feat=pointer-events – Neil Monroe Aug 14 '14 at 22:26
  • Since pointer-events are not supported in older browsers, disabled buttons will show the tooltip without having to make adjustments. :) – Gene Parcellano Aug 15 '14 at 19:43
  • 15
    This doesn't seem to work on `[disabled]` buttons. Also don't see Bootstrap (2.3.2) assigning pointer-events anywhere in source. – kangax Oct 13 '14 at 10:33
  • 1
    @kangax you're right, this will only work for buttons disabled via the bs 'disabled' class. Balexand's answer (http://stackoverflow.com/a/19938049/1794871) will work best in that case. Thanks for pointing that out. – Gene Parcellano Oct 18 '14 at 19:14
  • 7
    In a bootstrap3 angular app, after applying this style, the disabled button is now clickable – Dimitri Kopriwa Feb 11 '15 at 16:58
  • for `[disabled]` buttons use this: `.btn[disabled]{ pointer-events: auto; } ` – Esteve Jul 15 '15 at 12:18
  • By far the best answer. Thanks! – Pierre Aug 21 '15 at 05:27
  • I was excited when I found this, but unfortunately this does not work in the latest Firefox builds (40+), but works great in Chrome. I'll need to find another solution. – Aaron Oct 17 '15 at 19:48
  • @Aaron I tried it on my FF (41.0.2) and it works just fine. Make sure that your selector is specific enough, since it could be getting overridden. #id .btn.disabled {...} or .parentclass .btn.disabled {...}. Good luck. – Gene Parcellano Oct 19 '15 at 15:36
  • 3
    I tried to use this on an anchor with btn class. It _looked_ disabled and the tooltip worked, but I could click on the link (should not be possible). – Olle Härstedt Jul 27 '16 at 10:33
  • 1
    @OlleHärstedt I think the disabled attribute only affects – Gene Parcellano Jul 27 '16 at 15:00
  • 1
    For `[disabled]` buttons the approach `.btn[disabled]{ pointer-events: auto; }` doesn't work in IE11. It's easier to use `.disabled` css class. – kolobok Dec 14 '16 at 14:24
  • 1
    On Bootstrap 4 it works but you have to make it "important": `.btn.disabled { pointer-events: auto !important; }` – Adriano Pedro Dec 11 '18 at 12:01
  • I spent HOURS trying to figure out why tooltips on items that explained why links were disabled weren't working. I had disabled the links by setting pointer-events to none as was recommended on another SO article. xP Finally stumbled across this gem. To reconcile these two issues, I ended up doing a conditional [attr.href] in my angular statement to set the href to null when the link was disabled to prevent click events instead of disabling pointer events. – AForsberg Aug 23 '21 at 17:55
28

If you're desperate (like i was) for tooltips on checkboxes, textboxes and the like, then here is my hackey workaround:

$('input:disabled, button:disabled').after(function (e) {
    d = $("<div>");
    i = $(this);
    d.css({
        height: i.outerHeight(),
        width: i.outerWidth(),
        position: "absolute",
    })
    d.css(i.offset());
    d.attr("title", i.attr("title"));
    d.tooltip();
    return d;
});

Working examples: http://jsfiddle.net/WB6bM/11/

For what its worth, I believe tooltips on disabled form elements is very important to the UX. If you're preventing somebody from doing something, you should tell them why.

nolanpro
  • 2,257
  • 3
  • 23
  • 23
  • 1
    This should be the correct answer. Doesn't seem hackey to me at all :) – Starkers Feb 14 '14 at 09:24
  • 9
    What a nightmare for something that should be baked in :( –  Apr 08 '14 at 18:18
  • 1
    This works well, but if your input positions change based on the window size (like if your form elements wrap/move) you will need to add some handling on $(window).resize to move the tooltip div around, or they will appear in the wrong place. I recommend combining with CMS's answer from here: http://stackoverflow.com/questions/2854407/javascript-jquery-window-resize-how-to-fire-after-the-resize-is-completed – knighter Apr 26 '16 at 16:17
  • surprised at the amount of upvotes for this. Way too much code for something that can have a simple workaround. – Manny Alvarado Oct 09 '20 at 17:41
21

Based on Bootstrap 4

Disabled elements Elements with the disabled attribute aren’t interactive, meaning users cannot focus, hover, or click them to trigger a tooltip (or popover). As a workaround, you’ll want to trigger the tooltip from a wrapper or , ideally made keyboard-focusable using tabindex="0", and override the pointer-events on the disabled element.

<span class="d-inline-block" tabindex="0" data-toggle="tooltip" title="Disabled tooltip">
  <button class="btn btn-primary" style="pointer-events: none;" type="button" disabled>Disabled button</button>
</span>

All the details here: Bootstrap 4 doc

gon250
  • 3,405
  • 6
  • 44
  • 75
19

Here is some working code: http://jsfiddle.net/mihaifm/W7XNU/200/

$('body').tooltip({
    selector: '[rel="tooltip"]'
});

$(".btn").click(function(e) {
    if (! $(this).hasClass("disabled"))
    {
        $(".disabled").removeClass("disabled").attr("rel", null);

        $(this).addClass("disabled").attr("rel", "tooltip");
    }
});

The idea is to add the tooltip to a parent element with the selector option, and then add/remove the rel attribute when enabling/disabling the button.

mihai
  • 37,072
  • 9
  • 60
  • 86
  • 5
    It's the accepted answer because it worked in 2012, when it was answered. Things have changed since then, mainly the external resources used in the fiddle. I added new URLs to bootstrap cdn, code is still the same. – mihai May 25 '17 at 07:43
  • 3
    Can I get an updated fix for this for Bootstrap version 4.1? – Jason Ayer Oct 17 '18 at 15:35
  • fiddle ain't working in Firefox (at least) – RASMiranda Feb 25 '21 at 08:14
9

These workarounds are ugly. I've debugged the problem is that bootstrap automatically set CSS property pointer-events: none on disabled elements.

This magic property causes that JS is not able to handle any event on elements that matches CSS selector.

If you overwrite this property to default one, everything works like a charm, including tooltips!

.disabled {
  pointer-events: all !important;
}

However you shouldn't use so general selector, because you will probably have to manually stop JavaScript event propagation way you know (e.preventDefault()).

lukyer
  • 7,595
  • 3
  • 37
  • 31
9

If it helps anyone, I was able to get a disabled button to show a tooltip by simply putting a span inside it and applying the tooltip stuff there, angularjs around it...

<button ng-click="$ctrl.onClickDoThis()"
        ng-disabled="!$ctrl.selectedStuff.length">
  <span tooltip-enable="!$ctrl.selectedStuff.length"
        tooltip-append-to-body="true"
        uib-tooltip="Select at least one thing to enable button.">
    My Butt
  </span>
</button>
Nathan Beach
  • 2,497
  • 2
  • 24
  • 25
8

Try this example:

Tooltips must be initialized with jQuery: select the specified element and call the tooltip() method in JavaScript:

$(document).ready(function () {
    $('[data-toggle="tooltip"]').tooltip();
});

Add CSS:

.tool-tip {
  display: inline-block;
}

.tool-tip [disabled] {
  pointer-events: none;
}

And your html:

<span class="tool-tip" data-toggle="tooltip" data-placement="bottom" title="I am Tooltip">
    <button disabled="disabled">I am disabled</button>
</span>
Denis Bubnov
  • 2,619
  • 5
  • 30
  • 54
7

In my case, none of the above solutions worked. I found that it's easier to overlap the disabled button using an absolute element as:

<div rel="tooltip" title="I workz" class="wrap">
  <div class="overlap"></div>
  <button>I workz</button>
</div>

<div rel="tooltip" title="Boo!!" class="wrap poptooltip">
  <div class="overlap"></div>
  <button disabled>I workz disabled</button>
</div>

.wrap {
  display: inline-block;
  position: relative;
}

.overlap {
  display: none
}

.poptooltip .overlap {
  display: block;
  position: absolute;
  height: 100%;
  width: 100%;
  z-index: 1000;
}

Demo

vorillaz
  • 6,098
  • 2
  • 30
  • 46
4

You can't get the tool-tip to show on a disabled button. This is because disabled elements don't trigger any events, including the tool-tip. Your best bet would be to fake the button being disabled (so it looks and acts like its disabled), so you can then trigger the tool-tip.

Eg. Javascript:

$('[rel=tooltip].disabled').tooltip();

$('[rel=tooltip].disabled').bind('click', function(){
     return false;
});

Instead of just $('[rel=tooltip]').tooltip();​

HTML:

<hr>
<button class="btn disabled" rel="tooltip" data-title="Dieser Link führt zu Google">button disabled</button>

<button class="btn" rel="tooltip" data-title="Dieser Link führt zu Google">button not disabled</button>

JSFiddle: http://jsfiddle.net/BA4zM/75/

Adam
  • 1,214
  • 13
  • 23
4

You can simply override Bootstrap's "pointer-events" style for disabled buttons via CSS e.g.

.btn[disabled] {
 pointer-events: all !important;
}

Better still be explicit and disable specific buttons e.g.

#buttonId[disabled] {
 pointer-events: all !important;
}
Ben Smith
  • 19,589
  • 6
  • 65
  • 93
2

This is what myself and tekromancr came up with.

Example element:

<a href="http://www.google.com" id="btn" type="button" class="btn btn-disabled" data-placement="top" data-toggle="tooltip" data-title="I'm a tooltip">Press Me</a>

note: the tooltip attributes can be added to a separate div, in which the id of that div is to be used when calling .tooltip('destroy'); or .tooltip();

this enables the tooltip, put it in any javascript that is included in the html file. this line might not be necessary to add, however. (if the tooltip shows w/o this line then don't bother including it)

$("#element_id").tooltip();

destroys tooltip, see below for usage.

$("#element_id").tooltip('destroy');

prevents the button from being clickable. because the disabled attribute is not being used, this is necessary, otherwise the button would still be clickable even though it "looks" as if it is disabled.

$("#element_id").click(
  function(evt){
    if ($(this).hasClass("btn-disabled")) {
      evt.preventDefault();
      return false;
    }
  });

Using bootstrap, the classes btn and btn-disabled are available to you. Override these in your own .css file. you can add any colors or whatever you want the button to look like when disabled. Make sure you keep the cursor: default; you can also change what .btn.btn-success looks like.

.btn.btn-disabled{
    cursor: default;
}

add the code below to whatever javascript is controlling the button becoming enabled.

$("#element_id").removeClass('btn-disabled');
$("#element_id").addClass('btn-success');
$('#element_id).tooltip('destroy');

tooltip should now only show when the button is disabled.

if you are using angularjs i also have a solution for that, if desired.

  • I came across some problem when using `destroy` on tooltip. (See [this](https://github.com/twbs/bootstrap/issues/20511)) However, `$("#element_id").tooltip('disable')` and `$("#element_id").tooltip('enable')` work for me. – Sam Kah Chiin Jul 13 '17 at 09:07
1

Working code for Bootstrap 3.3.6

Javascript:

$('body').tooltip({
  selector: '[data-toggle="tooltip"]'
});

$(".btn").click(function(e) {
 if ($(this).hasClass("disabled")){
   e.preventDefault();
 }
});

CSS:

a.btn.disabled, fieldset[disabled] a.btn {
  pointer-events: auto;
}
Nerian
  • 15,901
  • 13
  • 66
  • 96
1

You can imitate the effect using CSS3.

Simply take the disabled state off the button and the tooltip doesn't appear anymore.. this is great for validation as the code requires less logic.

I wrote this pen to illustrate.

CSS3 Disabled Tooltips

[disabled] {
  &[disabled-tooltip] {
    cursor:not-allowed;
    position: relative;
    &:hover {
      &:before {
        content:'';
        border:5px solid transparent;
        border-top:5px solid black;
        position: absolute;
        left: 50%;
        transform: translate(-50%, calc(-100% + -5px));
      }
      &:after {
        content: attr(disabled-tooltip);
        position: absolute;
        left: 50%;
        transform: translate(-50%, calc(-100% + -15px));
        width:280px;
        background-color:black;
        color:white;
        border-radius:5px;
        padding:8px 12px;
        white-space:normal;
        line-height:1;
      }
    }
  }
}

<button type="button" class="btn btn-primary" disabled-tooltip="I am a disabled tooltip using CSS3.. You can not click this button." disabled>Primary Button</button>
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
beau
  • 11
  • 2
1

Simply add the disabled class to the button instead of the disabled attribute to make it visibly disabled instead.

<button class="btn disabled" rel="tooltip" data-title="Dieser Link führt zu Google">button disabled</button>

Note: this button only appears to be disabled, but it still triggers events, and you just have to be mindful of that.

Mystical
  • 2,505
  • 2
  • 24
  • 43
  • This is not a great answer for the simple reason that your solution, essentially, is to turn a "disabled button" into a "button that appears disabled". These are not the same thing. – osullic Aug 23 '23 at 14:15
1

I finally solved this problem, at least with Safari, by putting "pointer-events: auto" before "disabled". The reverse order didn't work.

0

pointer-events: auto; does not work on an <input type="text" />.

I took a different approach. I do not disable the input field, but make it act as disabled via css and javascript.

Because the input field is not disabled, the tooltip is displayed properly. It was in my case way simpler than adding a wrapper in case the input field was disabled.

$(document).ready(function () {
  $('.disabled[data-toggle="tooltip"]').tooltip();
  $('.disabled').mousedown(function(event){
    event.stopImmediatePropagation();
    return false;
  });
});
input[type=text].disabled{
  cursor: default;
  margin-top: 40px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.3.3/js/tether.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"> 
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>


<input type="text" name="my_field" value="100" class="disabled" list="values_z1" data-toggle="tooltip" data-placement="top" title="this is 10*10">
John Smith
  • 489
  • 1
  • 6
  • 12
0

For Bootstrap 3

HTML

<button 
    class="btn btn-success" 
    disabled
    data-hint="Enabled">
  <div class="sp-btn-overlap" data-hint="Disabled"></div>
  Submit button
</button>

CSS

button { position:relative; }

.sp-btn-overlap { 
    position:absolute; 
    top:0; 
    left:0; 
    height:100%; 
    width:100%; 
    background:none; 
    border:none; 
    z-index:1900;
}

JS

$('button .sp-btn-overlap')
    .popover({
        trigger: 'hover',
        container: 'body',
        placement: 'bottom',
        content: function() {
            return $(this).parent().prop('disabled')
                    ? $(this).data('hint')
                    : $(this).parent().data('hint');
            }
        });

$('button .sp-btn-overlap')
  .popover({
    trigger: 'hover',
    container: 'body',
    placement: 'bottom',
    content: function() {
      return $(this).parent().prop('disabled')
                  ? $(this).data('hint')
                  : $(this).parent().data('hint'); }
  });
button {
  position:relative; /* important! */
}

.sp-btn-overlap {
  position:absolute;
  top:0;
  left:0;
  height:100%;
  width:100%;
  background:none;
  border:none;
  z-index:1900;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>

<button disabled class="btn btn-default" data-hint="Enabled">
  <div class="sp-btn-overlap" data-hint="Disabled"></div>
  Disabled button
</button>

<button class="btn btn-default" data-hint="Enabled">
  <div class="sp-btn-overlap" data-hint="Disabled"></div>
  Enabled button
</button>
0

I had the same issue on Dynamic controls so I just simply do it by, Set style attributes and enable the read-only property = true when we need the element as disabled but show the tooltip if user click on the input button controls.

Yes disabled stopped all event functions like ObBlur, onClick /OnFocus. in place of below line :

((document.getElmentByName('MYINPUTBTN').item(0))).disabled= true;

we can do thru below code after that tooltip will be enabled in disabled input button elements.

((document.getElmentByName('MYINPUTBTN').item(0))).setAttribute("style", "background-color": #e9ecef;");

b

Hope this will resolve the issue.

Ashutosh Soni
  • 191
  • 1
  • 4
0

Bootstrap 5

For me I needed to do the opposite of what @nathan-beach suggested. I put the span OUTSIDE the button:

<span data-bs-toggle="tooltip" data-bs-title="You can only refresh if 24 hours has passed or there are new reviews">
  <button type="button" class="btn btn-primary" disabled>
    <i class="fa-duotone fa-arrows-rotate"></i> Rebuild
  </button>
</span>

(and the the regular stuff to enable tooltips).

phil
  • 4,668
  • 4
  • 33
  • 51
-1

Just override the css that disables hover events on your element

add css:

pointer-events: all !important;
cursor: not-allowed !important;

This will disable clicks on the button, but will still allow hover events enabling for tooltips to work

L4marr
  • 291
  • 2
  • 16