4

I am reading css-tricks and in the end I can see the following.

Using an HTML5 data attribute, then pulling that attribute in and styling it as a pseudo element, we can create completely custom tooltips through CSS.

enter image description here

The problem is that the link inside of the article is dead, and I am not such a good html/css guy to be able to understand how to do this. Can anyone help?

Harry
  • 87,580
  • 25
  • 202
  • 214
Salvador Dali
  • 214,103
  • 147
  • 703
  • 753
  • 1
    You can do it like [this](http://jsfiddle.net/hari_shanx/1rbnLbbx/) mate. *Note:* It doesn't have the arrow shape at the bottom but that can be achieved with a little more work :) – Harry Aug 09 '14 at 02:19
  • This is the non-broken version of the link: http://codepen.io/css-tricks/pen/wFeaG/ – ralph.m Aug 09 '14 at 03:04
  • This is a great website to keep update.. Here you can see how to create tooltip with data attribute.http://webdesign.tutsplus.com/articles/quick-tip-tooltips-courtesy-of-html5-data-attributes--webdesign-4826. – Kheema Pandey Aug 09 '14 at 03:20
  • Added a [canonical answer here](http://stackoverflow.com/a/25836471/2680216). – Josh Crozier Sep 14 '14 at 18:25

4 Answers4

8

JSFiddle is here. Note: The original content is here.

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

.tooltip:hover {
  color: #c00;
  text-decoration: none;
}

.tooltip:hover:after {
  background: #111;
  background: rgba(0, 0, 0, .8);
  border-radius: .5em;
  bottom: 1.35em;
  color: #fff;
  content: attr(title);
  display: block;
  left: 1em;
  padding: .3em 1em;
  position: absolute;
  text-shadow: 0 1px 0 #000;
  white-space: nowrap;
  z-index: 98;
}

.tooltip:hover:before {
  border: solid;
  border-color: #111 transparent;
  border-color: rgba(0, 0, 0, .8) transparent;
  border-width: .4em .4em 0 .4em;
  bottom: 1em;
  content: "";
  display: block;
  left: 2em;
  position: absolute;
  z-index: 99;
}
<p>Vestibulum mollis mauris <a href="#" class="tooltip" title="Sample tooltip">pellentesque</a></p>
Mohammad Faisal
  • 2,144
  • 15
  • 26
Sodbileg Gansukh
  • 1,730
  • 2
  • 13
  • 19
  • 4
    Nice solution, however instead of the `title` attribute I'd use the HTML5 data attributes (e.g. `data-title`) in order to prevent the browser to display the default tooltip. – roibeart Feb 18 '16 at 11:51
6

The good answers have already been given, but they all lack generality. Hence, I want to provide a more general solution to create tooltips with just span and its pseudo-elements (before and after) which provides positions also using data attributes.

Here is the markup for a span element.

  <span 
    class="tooltip"
    data-tooltip-position="right"
    data-tooltip="Only gmail will be accepted!">?</span>

And here is final code snippet:

body {
  margin: 0;
  background-color: #359;
}

.form-box {
  position: relative;
  width: 400px;
  padding: 50px 60px;
  margin: 5% auto;
  background-color: rgb(240, 230, 255);
  border-radius: 10px;
  text-align: center;
}

.form-box > input[type='text'] {
  box-sizing: border-box;
  padding: 8px;
  border-radius: 5px;
  outline: none;
  border: 2px solid #aaa;
  transition: all 0.2s ease-out;
}

.form-box > input:focus {
   border-color: dodgerblue;
   box-shadow: 0 0 8px 0 dodgerblue;
}

/* Tooltip Styles */

.tooltip {
  position: relative;
  padding: 5px 10px;
  margin-left: 15px;
  margin-right: 15px;
  background-color: rgb(56, 56, 56);
  border-radius: 50%;
  color: #fff;
  cursor: help;
  transition: all 0.2s ease-out;
}

.tooltip:hover {
  box-shadow: 0 0 6px 0 black;
}


.tooltip::before, .tooltip::after {
   position: absolute;
   left: 50%;
   opacity: 0;
   transition: all 0.2s ease-out;
}

.tooltip::before {
  content: "";
  border-width: 5px 4px 0 5px;
  border-style: solid;
  border-color: rgba(56, 56, 56, 0.8) transparent;
  margin-left: -4px;
  top: -8px;
}

.tooltip::after {
  content: attr(data-tooltip);
  top: -8px;
  width: 150px;
  margin-left: -75px;
  padding: 5px;
  font-size: 12px;
  background-color: rgba(56, 56, 56, 0.8);
  border-radius: 4px;
  transform: translate3d(0, -100%, 0);
  pointer-events: none;
}

/* 4 tooltip positions */

.tooltip[data-tooltip-position='left']::before {
  margin-left: -21px;
  top: 12px;
  transform: rotate(-90deg);
}

.tooltip[data-tooltip-position='left']::after {
  transform: translate3d(-65%, 40%, 0);
}

.tooltip[data-tooltip-position='right']::before {
  margin-left: 14px;
  top: 12px;
  transform: rotate(90deg);
}

.tooltip[data-tooltip-position='right']::after {
  transform: translate3d(60%, 40%, 0);
}

.tooltip[data-tooltip-position='bottom']::before {
  margin-left: -4px;
  top: 32px;
  transform: rotate(-180deg);
}

.tooltip[data-tooltip-position='bottom']::after {
  transform: translate3d(0, 186%, 0);
}

/* end of 4 tooltip positions */

.tooltip:hover::before, .tooltip:hover::after {
  opacity: 1;
}
<div class="form-box">

  <span 
    class="tooltip"
    data-tooltip-position="left"
    data-tooltip="Only gmail will be accepted!">?</span>

  <span 
    class="tooltip"
    data-tooltip-position="up"
    data-tooltip="Only gmail will be accepted!">?</span>

  <input type="text" class="input" placeholder="Email">
  

    
  <span 
    class="tooltip"
    data-tooltip-position="bottom"
    data-tooltip="Only gmail will be accepted!">?</span>    
    
  <span 
    class="tooltip"
    data-tooltip-position="right"
    data-tooltip="Only gmail will be accepted!">?</span>

</div>
Humoyun Ahmad
  • 2,875
  • 4
  • 28
  • 46
  • How to invoke from a button click instead of hover? eg. ( invalid email address ) – patrick Jun 02 '22 at 17:49
  • @patrick I believe that would be an entirely different question with answers probably found here: https://stackoverflow.com/questions/59527327/how-to-show-tooltip-on-click-event-using-javascript – FrankenCode Jul 07 '22 at 12:45
4

You can achieve this by using the HTML5 data attributes, a couple of pseudo-elements and a bit of positioning like below:

a {
  position: relative;  /* to position the tooltip relative to the anchor tag */
}
a:hover {  /* for achieving the arrow shape at the bottom of the tooltip */
  text-decoration: none;
}
a::after,
a::before {
  position: absolute;
  display: none;  /* initially hide it from view */
}
a::before {
  content: '';
  top: -2px;
  left: 6px;
  height: 0px;
  width: 0px;
  /* the arrow */
  border-left: 5px solid transparent;
  border-top: 5px solid #ffe4b5;
  border-right: 5px solid transparent;
}
a::after {
  content: attr(data-tooltip);  /* set content of pseudo element as the value of data-tooltip attribute */
  top: -25px;
  left: -5px;
  background: #ffe4b5;
  border-radius: 4px;  /* just a bit of extra styling */
  padding: 2px 6px;
  white-space: nowrap;
  color: black;
}
a:hover::after,
a:hover::before {
  display: block;  /* display both tooltip and arrow mark when a is hovered on */
}

/* Just for demo */

* {
  font-family: Calibri;
}
.wrapper {
  margin: 25px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<!-- the data-tooltip attribute in the a tag has the tooltip's contents -->
<div class='wrapper'>Some long long text blah blah with some <a href='#' data-tooltip='Tooltip'>link</a> inside it.
  <br/>Some more text blah blah with some <a href='#' data-tooltip='Long Tooltip'>link</a> inside it</div>

You can also use the title attribute for the tooltip content. That will make fallback easy in older browsers also. Also, I have used some generic selectors, you can make it more specific.


Advanced Sample: Below is a more advanced version of the tool-tip with borders and transition effects achieved using CSS3 properties.

a {
  position: relative;
}
a:hover {
  text-decoration: none;
}
a::after,
a::before {
  position: absolute;
  visibility: hidden;
  background: #ffe4b5;
  border: 1px solid #f3b445;
  opacity: 0;
  transition: all 0.4s ease-out;
}
a:hover::after,
a:hover::before {
  visibility: visible;
  opacity: 1;
}
a::before {
  content: '';
  top: -3px;
  left: 6px;
  height: 4px;
  width: 4px;
  border-color: transparent #f3b445 #f3b445 transparent;
  transform: rotate(45deg);
  z-index: 2;
}
a::after {
  content: attr(data-tooltip);
  top: -25px;
  left: -5px;
  border-radius: 4px;
  padding: 2px 6px;
  white-space: nowrap;
  color: black;
}
/* Just for demo */

* {
  font-family: Calibri;
}
.wrapper {
  margin: 25px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='wrapper'>Some long long text blah blah with some <a href='#' data-tooltip='Tooltip'>link</a> inside it.
  <br/>Some more text blah blah with some <a href='#' data-tooltip='Long Tooltip'>link</a> inside it</div>

Points to note:

  1. Transitions on pseudo elements is well supported in Firefox but doesn't work on Chrome v24 (and less). For the browsers that don't support it, there would be no transition effect.
  2. The sample with a border to the tool-tip uses CSS3 transforms for the arrow and hence would need a CSS3 compatible browser to work properly.
Harry
  • 87,580
  • 25
  • 202
  • 214
0

I can see that the accepted answer has been already provided using attr css method. But if we hover over our element, we find that the default browser tooltip also appears along with the custom tooltip. This isn't a correct approach in terms of user experience.

So creating 2 CSS classes with absolute positioning on a tooltip element like span would still provide a

reusable tooltip experience

You can find the code here and video here.

Abhishek Tewari
  • 387
  • 3
  • 12