338

Example:

<a href="example.com" title="My site"> Link </a>

How do I change the presentation of the "title" attribute in the browser?. By default, it just has yellow background and small font. I would like to make it bigger and change the background color.

Is there a CSS way to style the title attribute?

Dr. Hans-Peter Störr
  • 25,298
  • 30
  • 102
  • 139
Kunpha
  • 3,511
  • 3
  • 18
  • 5
  • I've made a tiny script which does that called [title-tooltips](https://github.com/yairEO/title-tooltip) – vsync Feb 22 '21 at 22:15

10 Answers10

205

It seems that there is in fact a pure CSS solution, requiring only the css attr expression, generated content and attribute selectors (which suggests that it works as far back as IE8):

https://jsfiddle.net/z42r2vv0/2/

a {
  position: relative;
  display: inline-block;
  margin-top: 20px;
}

a[title]:hover::after {
  content: attr(title);
  position: absolute;
  top: -100%;
  left: 0;
}
<a href="http://www.google.com/" title="Hello world!">
  Hover over me
</a>

update w/ input from @ViROscar: please note that it's not necessary to use any specific attribute, although I've used the "title" attribute in the example above; actually my recommendation would be to use the "alt" attribute, as there is some chance that the content will be accessible to users unable to benefit from CSS.

update again I'm not changing the code because the "title" attribute has basically come to mean the "tooltip" attribute, and it's probably not a good idea to hide important text inside a field only accessible on hover, but if you're interested in making this text accessible the "aria-label" attribute seems like the best place for it: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute

mplungjan
  • 169,008
  • 28
  • 173
  • 236
jrz
  • 4,286
  • 1
  • 29
  • 21
  • 18
    And if you do not wish for the native tooltip to eventually display as well, you can always use the "alt" tag.. – jrz Jul 10 '13 at 21:32
  • 2
    @Jonz i've tried with a custom property "data-alt='alt'" and everything goes ok. is not necessary to use the alt or title property. – ViROscar Jan 23 '15 at 15:27
  • 18
    Pure CSS Tooltips has serious wrawback -- they are bounded to the element, thus bounded to its [`stacking context`](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context). All elements with `position` other than `static` creates new *stacking context* and pure CSS tooltips are not visible outside nor can go beyond such *stacking context*, so if you have tight element with position `relative`, your CSS tooltip will not be visible. The only solution is attaching tooltip to top *stacking context* (e.g. ``) which needs JavaScript. – Rudolf Gröhling Sep 23 '16 at 21:34
  • unfortunately it doesn't disappear on click. – Florian G Oct 11 '16 at 23:18
  • 4
    I know this is a really old reply, but this is the only one I've found that is really useful. I recommend using aria-label instad of alt or title as it costs nothing and it will help people with acessibility.. – lbutlr Jul 02 '20 at 20:23
  • I would use a HTML data attribute e.g. data-tooltip a[data-tooltip]:hover:after { content: attr(data-tooltip); } – Ollie Williams Apr 05 '22 at 11:01
  • 1
    Doesn't work for me. The title attribute seems to be handled by the browser, at least for Chrome, and can't be styled. – David Spector Aug 12 '23 at 09:23
194

You can't style an actual title attribute

How the text in the title attribute is displayed is defined by the browser and varies from browser to browser. It's not possible for a webpage to apply any style to the tooltip that the browser displays based on the title attribute.

However, you can create something very similar using other attributes.

You can make a pseudo-tooltip with CSS and a custom attribute (e.g. data-title)

For this, I'd use a data-title attribute. data-* attributes are a method to store custom data in DOM elements/HTML. There are multiple ways of accessing them. Importantly, they can be selected by CSS.

Given that you can use CSS to select elements with data-title attributes, you can then use CSS to create :after (or :before) content that contains the value of the attribute using attr().

Styled tooltip Examples

Bigger and with a different background color (per question's request):

[data-title]:hover:after {
    opacity: 1;
    transition: all 0.1s ease 0.5s;
    visibility: visible;
}
[data-title]:after {
    content: attr(data-title);
    background-color: #00FF00;
    color: #111;
    font-size: 150%;
    position: absolute;
    padding: 1px 5px 2px 5px;
    bottom: -1.6em;
    left: 100%;
    white-space: nowrap;
    box-shadow: 1px 1px 3px #222222;
    opacity: 0;
    border: 1px solid #111111;
    z-index: 99999;
    visibility: hidden;
}
[data-title] {
    position: relative;
}
<a href="example.com" data-title="My site"> Link </a> with styled tooltip (bigger and with a different background color, as requested in the question)<br/>
<a href="example.com" title="My site"> Link </a> with normal tooltip

More elaborate styling (adapted from this blog post):

[data-title]:hover:after {
    opacity: 1;
    transition: all 0.1s ease 0.5s;
    visibility: visible;
}
[data-title]:after {
    content: attr(data-title);
    position: absolute;
    bottom: -1.6em;
    left: 100%;
    padding: 4px 4px 4px 8px;
    color: #222;
    white-space: nowrap; 
    -moz-border-radius: 5px; 
    -webkit-border-radius: 5px;  
    border-radius: 5px;  
    -moz-box-shadow: 0px 0px 4px #222;  
    -webkit-box-shadow: 0px 0px 4px #222;  
    box-shadow: 0px 0px 4px #222;  
    background-image: -moz-linear-gradient(top, #f8f8f8, #cccccc);  
    background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #f8f8f8),color-stop(1, #cccccc));
    background-image: -webkit-linear-gradient(top, #f8f8f8, #cccccc);  
    background-image: -moz-linear-gradient(top, #f8f8f8, #cccccc);  
    background-image: -ms-linear-gradient(top, #f8f8f8, #cccccc);  
    background-image: -o-linear-gradient(top, #f8f8f8, #cccccc);
    opacity: 0;
    z-index: 99999;
    visibility: hidden;
}
[data-title] {
    position: relative;
}
<a href="example.com" data-title="My site"> Link </a> with styled tooltip<br/>
<a href="example.com" title="My site"> Link </a> with normal tooltip

Known issues

Unlike a real title tooltip, the tooltip produced by the above CSS is not, necessarily, guaranteed to be visible on the page (i.e. it might be outside the visible area). On the other hand, it is guaranteed to be within the current window, which is not the case for an actual tooltip.

In addition, the pseudo-tooltip is positioned relative to the element that has the pseudo-tooltip rather than relative to where the mouse is on that element. You may want to fine-tune where the pseudo-tooltip is displayed. Having it appear in a known location relative to the element can be a benefit or a drawback, depending on the situation.

You can't use :before or :after on elements which are not containers

There's a good explanation in this answer to "Can I use a :before or :after pseudo-element on an input field?"

Effectively, this means that you can't use this method directly on elements like <input type="text"/>, <textarea/>, <img>, etc. The easy solution is to wrap the element that's not a container in a <span> or <div> and have the pseudo-tooltip on the container.

Examples of using a pseudo-tooltip on a <span> wrapping a non-container element:

[data-title]:hover:after {
    opacity: 1;
    transition: all 0.1s ease 0.5s;
    visibility: visible;
}
[data-title]:after {
    content: attr(data-title);
    background-color: #00FF00;
    color: #111;
    font-size: 150%;
    position: absolute;
    padding: 1px 5px 2px 5px;
    bottom: -1.6em;
    left: 100%;
    white-space: nowrap;
    box-shadow: 1px 1px 3px #222222;
    opacity: 0;
    border: 1px solid #111111;
    z-index: 99999;
    visibility: hidden;
}
[data-title] {
    position: relative;
}

.pseudo-tooltip-wrapper {
    /*This causes the wrapping element to be the same size as what it contains.*/
    display: inline-block;
}
Text input with a pseudo-tooltip:<br/>
<span class="pseudo-tooltip-wrapper" data-title="input type=&quot;text&quot;"><input type='text'></span><br/><br/><br/>
Textarea with a pseudo-tooltip:<br/>
<span class="pseudo-tooltip-wrapper" data-title="this is a textarea"><textarea data-title="this is a textarea"></textarea></span><br/>

From the code on the blog post linked above (which I first saw in an answer here that plagiarized it), it appeared obvious to me to use a data-* attribute instead of the title attribute. Doing so was also suggested in a comment by snostorm on that (now deleted) answer.

Makyen
  • 31,849
  • 12
  • 86
  • 121
  • 2
    This may not the answer to the question, but this is the best solution so far. Thanks. – JJ Labajo Nov 16 '18 at 15:44
  • 3
    @JJLabajo Thanks for the complement about this being the best solution so far. However, I'm not sure how this doesn't answer the question. The question is asking for something that's just not possible. This answer says it's not possible, but offers an alternative that accomplishes something similar to what the OP desires. – Makyen Dec 26 '18 at 14:38
  • I think this solution does not apply to elements like `input[type='text']` or `textarea`, but I don't know why. Can anyone explain? – Cheeso Sep 27 '19 at 19:48
  • @Cheeso You're correct, the `:before` and `:after` pseudo-elements don't work on elements which are not containers. There's a good explanation in the answer: [Can I use a :before or :after pseudo-element on an input field?](https://stackoverflow.com/a/4660434) To use this method, it is probably easiest to wrap the elements which are not containers in a `` or `
    ` on which you put the `data-title` attribute. You'll probably also want to give them `display: inline-block;`, as that will make them the same size as the `` or `
    – Makyen Sep 28 '19 at 08:31
  • 4
    This answer actually teaches us what's going on and provides all kinds of well-structured background information. – Ideogram Oct 30 '19 at 07:23
  • Suppose if we use required for input attribute we will get two title, one is the default one and another one is the customized one. how to hide the default one: '


    ' Textarea with a pseudo-tooltip:
    ' @Makyen
    – AVINASH M Nov 28 '19 at 06:39
  • @AVINASHM, If you do something that causes a browser defined tooltip to appear, there's nothing you can do to prevent that from happening, other than to not do the thing which causes that tooltip to appear. In the specific case of using `required=true`, you will need to not use that attribute and implement your own validation for the form. Alternately, you can cause the pseudo tooltip to appear at a location which will not be occupied by the default tooltip. Where that could be will be browser specific, but you could implement CSS which covers the browsers you're interested in supporting. – Makyen Nov 28 '19 at 07:00
  • Other possibilities for using `required=true` are A) have JavaScript code that temporarily removes the `required` attribute whenever the mouse is hovered over an input element and then replaces it once the mouse moves out of the element. B) probably better: have JavaScript that moves all `required` attributes into something like `data-required` until the form is in the process of being submitted, then restore those attributes to `required` while the `submit` is occurring. After the submit and its verification is complete, then put them back to `data-required`. – Makyen Nov 28 '19 at 07:00
  • Do we have any code snippet related to this for reference https://stackblitz.com/edit/angular-pa2lnu @Makyen – AVINASH M Nov 28 '19 at 07:17
  • @AVINASHM I don't, currently, have any code that does either of the solutions I mentioned above. However, it shouldn't be that difficult to write something which accomplishes either of the two JavaScript possibilities I mentioned. – Makyen Nov 28 '19 at 08:56
  • The solution is good, but.. The tooltip is displayed on one line. If the tooltip text is 100-150 characters, then without wrapping the line it does not look beautiful. [jsfiddle](https://jsfiddle.net/5rw1tnxa/) – Arsen Feb 02 '20 at 16:06
  • 1
    @Arsen I'm not sure why you have an issue. Obviously, you'd adjust the CSS such that the tooltip would look good in the context in which you are using it. What's used here was intended only as a proof of concept and to implement the specific formatting requested in the question. If you want the words to wrap, it's trivial to remove the `white-space: nowrap;` and apply other CSS properties (e.g. `width`, `height`, `max-width`, `max-height`, etc.). The actual CSS used wasn't intended as the end-all be-all for all situations, but only to demonstrate a way to accomplish the requested task. – Makyen Feb 02 '20 at 21:20
  • @Arsen If you need more intricate formatting than what's possible with this, there are more complex options for tooltip-like displays (i.e. that appear on hover). However, those require more significant HTML changes and/or JavaScript, which are outside what was asked for in this question, which asks for a CSS solution "to make it bigger and change the background color." For example, I use an HTML and CSS solution to produce [this tooltip](https://i.stack.imgur.com/AhVZf.png) for my [Roomba Forecaster](//stackapps.com/questions/7239) userscript. – Makyen Feb 02 '20 at 21:20
  • Yes, the concept is clear. CSS issue. The wrapper should be the width of the characters. And limited to the max-width parameter. [Sample](http://s25.znimg.ru/1580758560/xozup5mvnt.png). Removing white-space does not help. What needs to be changed to get it like on a sample? – Arsen Feb 03 '20 at 19:47
  • Any quick tip for hiding blank rows where this logic might be used in a table? I could use PHP but curious if CSS solution for blank values. – Daniel Mar 09 '20 at 03:14
  • @Daniel I'm not really sure what you're asking. I have a few guesses as to what you mean, but how to solve it really depends on the situation you're working with. The long and short of it is that what I *think* you're asking about really deserves it's [own question](https://stackoverflow.com/questions/ask), so you can fully describe the issue you're dealing with, and so you can get input/answers from multiple people. – Makyen Mar 09 '20 at 03:22
  • @Makyen, I was asking if you implement this on hover over a table cell, how to prevent if that cell is blank. I solved via PHP: $notes = trim($row['notes']); $data_title = ' data-title="' . $notes . '" '; . . . and then in the rows for the attribute: echo strlen($notes)>0 ? $data_title : ''; and that worked great. – Daniel Mar 09 '20 at 13:52
  • This is an excellent answer. It provides very clear solutions. I have accomplished my goal of learning something new today:) – Woody Dec 21 '22 at 19:18
  • It will be responsive or not? – MhkAsif Jan 24 '23 at 10:32
  • @MhkAsif That's going to depend on the CSS styling you use on the `:after` or `:before` and the containing elements, so isn't really answerable, as it being responsive is up to you and how you define and implement responsiveness in your page. – Makyen Jan 24 '23 at 15:01
  • This appears to work okay with A elements, even if they are positioned. – David Spector Aug 12 '23 at 10:18
  • @DavidSpector RE: your edit suggestion: I'm unsure if the issue you're attempting to resolve is global. Adding `z-index:-1` to the `[data-title]`, on first glance, appears to be more specific to within your implementation, rather than a global issue. Using any `position` value along with a `z-index` which isn't `auto` forms a new stacking context, which may be needed, depending on how things are within the page. I'd appreciate it if you could provide an example, perhaps on [jsfiddle](//jsfiddle.net), of the issue you're trying to address, so I can get a better feel for if it's a global issue. – Makyen Aug 12 '23 at 15:18
149

Here is an example of how to do it:

a.tip {
    border-bottom: 1px dashed;
    text-decoration: none
}
a.tip:hover {
    cursor: help;
    position: relative
}
a.tip span {
    display: none
}
a.tip:hover span {
    border: #c0c0c0 1px dotted;
    padding: 5px 20px 5px 5px;
    display: block;
    z-index: 100;
    background: url(../images/status-info.png) #f0f0f0 no-repeat 100% 5%;
    left: 0px;
    margin: 10px;
    width: 250px;
    position: absolute;
    top: 10px;
    text-decoration: none
}
<a href="#" class="tip">Link<span>This is the CSS tooltip showing up when you mouse over the link</span></a>
Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
valli
  • 5,797
  • 2
  • 19
  • 9
  • 1
    doesn't work properly in FF if instead of the tag **a** use the tag, for instance, **td** – dnim Sep 27 '12 at 10:26
  • 7
    See http://sixrevisions.com/css/css-only-tooltips/ for an example of the above technique, with a detailed explanation. – George Oct 04 '12 at 23:22
  • 1
    When I do this, I see a double tool tip. The styled one, and then shortly after, the unstyled one pops over this one. This is on your fiddle. I am using chrome. Is this an abnormality? –  Jun 28 '14 at 22:04
  • 17
    An answer without the title attribute in the code has over 100 upvotes here...? – Ben Racicot Apr 29 '19 at 21:46
  • 3
    Doesn't even address the actual question...boo! – Matt Oct 16 '19 at 15:38
  • If it's going to be done like this, it needs a transition with a delay. Display is none transitionable but I think an opacity or sizing change would be fine. It depends on the use case but instant tooltips can be annoying especially if you have lots that appear over other elements – blake Jul 23 '20 at 07:24
  • If one has to deal with a overflows for the provided solution, one can look at https://stackoverflow.com/a/72718020/325868 – LeO Jun 22 '22 at 15:33
31

CSS can't change the tooltip appearance. It is browser/OS-dependent. If you want something different you'll have to use Javascript to generate markup when you hover over the element instead of the default tooltip.

cletus
  • 616,129
  • 168
  • 910
  • 942
27

I have found the answer here: http://www.webdesignerdepot.com/2012/11/how-to-create-a-simple-css3-tooltip/

my own code goes like this, I have changed the attribute name, if you maintain the title name for the attribute you end up having two popups for the same text, another change is that my text on hovering displays underneath the exposed text.

.tags {
  display: inline;
  position: relative;
}

.tags:hover:after {
  background: #333;
  background: rgba(0, 0, 0, .8);
  border-radius: 5px;
  bottom: -34px;
  color: #fff;
  content: attr(data-gloss);
  left: 20%;
  padding: 5px 15px;
  position: absolute;
  z-index: 98;
  width: 350px;
}

.tags:hover:before {
  border: solid;
  border-color: #333 transparent;
  border-width: 0 6px 6px 6px;
  bottom: -4px;
  content: "";
  left: 50%;
  position: absolute;
  z-index: 99;
}
<a class="tags" data-gloss="Text shown on hovering">Exposed text</a>
Andrés Chandía
  • 999
  • 1
  • 16
  • 32
12

I thought i'd post my 20 lines JavaScript solution here. It is not perfect, but may be useful for some depending on what you need from your tooltips.

When to use it

  • Automatically styles the tooltip for all HTML elements with a TITLE attribute defined (this includes elements dynamically added to the document in the future)
  • No Javascript/HTML changes or hacks required for every tooltip (just the TITLE attribute, semantically clear)
  • Very light (adds about 300 bytes gzipped and minified)
  • You want only a very basic styleable tooltip

When NOT to use

  • Requires jQuery, so do not use if you don't use jQuery
  • Bad support for nested elements that both have tooltips
  • You need more than one tooltip on the screen at the same time
  • You need the tooltip to disappear after some time

The code

// Use a closure to keep vars out of global scope
(function () {
    var ID = "tooltip", CLS_ON = "tooltip_ON", FOLLOW = true,
    DATA = "_tooltip", OFFSET_X = 20, OFFSET_Y = 10,
    showAt = function (e) {
        var ntop = e.pageY + OFFSET_Y, nleft = e.pageX + OFFSET_X;
        $("#" + ID).html($(e.target).data(DATA)).css({
            position: "absolute", top: ntop, left: nleft
        }).show();
    };
    $(document).on("mouseenter", "*[title]", function (e) {
        $(this).data(DATA, $(this).attr("title"));
        $(this).removeAttr("title").addClass(CLS_ON);
        $("<div id='" + ID + "' />").appendTo("body");
        showAt(e);
    });
    $(document).on("mouseleave", "." + CLS_ON, function (e) {
        $(this).attr("title", $(this).data(DATA)).removeClass(CLS_ON);
        $("#" + ID).remove();
    });
    if (FOLLOW) { $(document).on("mousemove", "." + CLS_ON, showAt); }
}());

Paste it anywhere, it should work even when you run this code before the DOM is ready (it just won't show your tooltips until DOM is ready).

Customize

You can change the var declarations on the second line to customize it a bit.

var ID = "tooltip"; // The ID of the styleable tooltip
var CLS_ON = "tooltip_ON"; // Does not matter, make it somewhat unique
var FOLLOW = true; // TRUE to enable mouse following, FALSE to have static tooltips
var DATA = "_tooltip"; // Does not matter, make it somewhat unique
var OFFSET_X = 20, OFFSET_Y = 10; // Tooltip's distance to the cursor

Style

You can now style your tooltips using the following CSS:

#tooltip {
    background: #fff;
    border: 1px solid red;
    padding: 3px 10px;
}
ChrisF
  • 857
  • 9
  • 9
  • 2
    Works great! Fix for a minor bug (if title is empty) can be found here: http://stackoverflow.com/questions/26702472/bug-fix-for-a-script-that-applies-css-to-the-title-attribute – Malasorte Nov 02 '14 at 18:10
  • If you move rapidly over an element I am getting an empty tooltip, even with the bug fix mentioned above. This is erratic and stops if I take off the $(this).removeAttr("title"). But of course I then get the standard help showing after a while. – Allen Conquest Oct 25 '17 at 09:47
8

A jsfiddle for custom tooltip pattern is Here

It is based on CSS Positioning and pseduo class selectors

Check MDN docs for cross-browser support of pseudo classes

    <!-- HTML -->
<p>
    <a href="http://www.google.com/" class="tooltip">
    I am a 
        <span> (This website rocks) </span></a>&nbsp; a developer.
</p>

    /*CSS*/
a.tooltip {
    position: relative;
}

a.tooltip span {
    display: none;    
}

a.tooltip:hover span, a.tooltip:focus span {
    display:block;
    position:absolute;
    top:1em;
    left:1.5em;
    padding: 0.2em 0.6em;
    border:1px solid #996633;
    background-color:#FFFF66;
    color:#000;
}
prasun
  • 7,073
  • 9
  • 41
  • 59
5

Native tooltip cannot be styled.

That being said, you can use some library that would show styles floating layers when element is being hovered (instead of the native tooltips, and suppress them) requiring little or no code modifications...

poncha
  • 7,726
  • 2
  • 34
  • 38
  • 1
    I don’t think you can suppress the native tooltips if an element has a `title` attribute. So if you set up your own tooltip implementation, it is better to use some other attribute (say, `data-tip`) instead of `title`. – Jukka K. Korpela Mar 29 '12 at 16:08
  • 1
    you can, if after you attach to the event you clear title attribute – poncha Mar 30 '12 at 08:49
  • 1
    I see your point, but it’s not about styling native tooltips; it’s about avoiding them (by modifying the DOM). – Jukka K. Korpela Mar 30 '12 at 10:26
  • @JukkaK.Korpela yep, and i said in my first sentence that it was impossible ;) – poncha Mar 30 '12 at 11:19
  • The benefit of using the title attribute and clearing it later is that the tooltip is still available if the user has JavaScript disabled. – JJJ May 09 '13 at 11:54
2

You cannot style the default browser tooltip. But you can use javascript to create your own custom HTML tooltips.

bfavaretto
  • 71,580
  • 16
  • 111
  • 150
-4
a[title="My site"] {
    color: red;
}

This also works with any attribute you want to add for instance:

HTML

<div class="my_class" anything="whatever">My Stuff</div>

CSS

.my_class[anything="whatever"] {
    color: red;
}

See it work at: http://jsfiddle.net/vpYWE/1/

shana.
  • 89
  • 1
  • 2