Tooltip on hover with inline CSS without ID

269 Views Asked by At

A tooltip shall be displayed on hovering over an a tag. Yet, these criteria apply:

  • no "a:hover" should be used, no CSS classes in the head tag, it must be done with inline CSS
  • it must be pure js, no library
  • it must work without predefined IDs so that it can be used generically (the pattern is always like this: a tag is followed by a span tag, while the span tag content is the tooltip content)
  • html formatting should be possible (at least, basic formatting like b, u, ul/ol/li)

I might already have it (using onmouseover/onmouseout) but only almost. See the code:

  • How to make it work that the tooltip is always displayed below the actual a tag (currently, it's always displayed below the first a)?
  • An a tag is used within a p tag. How to to make it work (the whole span is currently not hidden)?

function show(item) {
     const str = item.nextElementSibling;
     str.style.visibility = "visible";
  }
  function hide(item) {
    const str = item.nextElementSibling;
    str.style.visibility = "hidden";
  }
<a style="border-bottom: 1px dotted #000000; color: #000000; outline: none; cursor: help; text-decoration: none; position: relative;" href="#" onMouseOver="show(this)" onMouseOut="hide(this)">Info 1</a>
<span style="visibility: hidden; color: #000000; cursor: help; padding: 0.8em 1em; background: #FFFFAA; border: 1px solid #FFAD33; -webkit-border-radius: 5px; -webkit-box-shadow: 5px 5px rgba(0, 0, 0, 0.1); position: absolute; left: 1em; top: 2em; z-index: 99; margin-left: 0; width: 250px;"><b>Some info 1:</b><ul><li>test 1</li><li>test 2</li></ul></span>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>

<a style="border-bottom: 1px dotted #000000; color: #000000; outline: none; cursor: help; text-decoration: none; position: relative;" href="#" onMouseOver="show(this)" onMouseOut="hide(this)">Info 2</a>
<span style="visibility: hidden; color: #000000; cursor: help; padding: 0.8em 1em; background: #FFFFAA; border: 1px solid #FFAD33; -webkit-border-radius: 5px; -webkit-box-shadow: 5px 5px rgba(0, 0, 0, 0.1); position: absolute; left: 1em; top: 2em; z-index: 99; margin-left: 0; width: 250px;"><b>Some info 2</b><ul><li>test 1</li><li>test 2</li></ul></span>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>

<a style="border-bottom: 1px dotted #000000; color: #000000; outline: none; cursor: help; text-decoration: none; position: relative;" href="#" onMouseOver="show(this)" onMouseOut="hide(this)">Info 3</a>
<span style="visibility: hidden; color: #000000; cursor: help; padding: 0.8em 1em; background: #FFFFAA; border: 1px solid #FFAD33; -webkit-border-radius: 5px; -webkit-box-shadow: 5px 5px rgba(0, 0, 0, 0.1); position: absolute; left: 1em; top: 2em; z-index: 99; margin-left: 0; width: 250px;"><b>Some info 3</b><ul><li>test 1</li><li>test 2</li></ul></span>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<a style="border-bottom: 1px dotted #000000; color: #000000; outline: none; cursor: help; text-decoration: none; position: relative;" href="#" onMouseOver="show(this)" onMouseOut="hide(this)">(Info 4)</a>
<span style="visibility: hidden; color: #000000; cursor: help; padding: 0.8em 1em; background: #FFFFAA; border: 1px solid #FFAD33; -webkit-border-radius: 5px; -webkit-box-shadow: 5px 5px rgba(0, 0, 0, 0.1); position: absolute; left: 1em; top: 2em; z-index: 99; margin-left: 0; width: 250px;"><b>Some info 4</b><ul><li>test 1</li><li>test 2</li></ul></span> Lorem ipsum dolor sit amet, consectetur adipiscing elit. </p>

1

There are 1 best solutions below

1
On BEST ANSWER

I removed all the inline event handlers you used in your HTML.

Check the JS comments for my explanation on the code.

const tooltipPadding = { top: 32, left: 16, }; // The extra em padding you set on the span converted to px 
const hide = element => element.style.visibility = 'hidden'; // Hide function

function show({ target }) { // Destrucutring the event obejct to get only the targetted element
  const element = target.nextElementSibling;
  const { left, top } = target.getBoundingClientRect(); // To get the position of the hovered a tag

  element.style.visibility = "visible";

  // To set the top and left position of the element
  element.style.left = `${left + tooltipPadding.left}px`;
  element.style.top = `${top + tooltipPadding.top}px`;
  target.addEventListener('mouseleave', _ => hide(element), { once: true }); // Adding an event to the a tag on mouseleave to hide the span only once.
}

// Select all the a tag and add the mouseenter event listener
[...document.querySelectorAll('a')].forEach(a => a.addEventListener('mouseenter', show));
<a style="border-bottom: 1px dotted #000000; color: #000000; outline: none; cursor: help; text-decoration: none; position: relative;" href="#">Info 1</a>
<span style="visibility: hidden; color: #000000; cursor: help; padding: 0.8em 1em; background: #FFFFAA; border: 1px solid #FFAD33; -webkit-border-radius: 5px; -webkit-box-shadow: 5px 5px rgba(0, 0, 0, 0.1); position: absolute; left: 1em; top: 2em; z-index: 99; margin-left: 0; width: 250px;"><b>Some info 1:</b><ul><li>test 1</li><li>test 2</li></ul></span>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>

<a style="border-bottom: 1px dotted #000000; color: #000000; outline: none; cursor: help; text-decoration: none; position: relative;" href="#">Info 2</a>
<span style="visibility: hidden; color: #000000; cursor: help; padding: 0.8em 1em; background: #FFFFAA; border: 1px solid #FFAD33; -webkit-border-radius: 5px; -webkit-box-shadow: 5px 5px rgba(0, 0, 0, 0.1); position: absolute; left: 1em; top: 2em; z-index: 99; margin-left: 0; width: 250px;"><b>Some info 2</b><ul><li>test 1</li><li>test 2</li></ul></span>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
    
<a style="border-bottom: 1px dotted #000000; color: #000000; outline: none; cursor: help; text-decoration: none; position: relative;" href="#">Info 3</a>
<span style="visibility: hidden; color: #000000; cursor: help; padding: 0.8em 1em; background: #FFFFAA; border: 1px solid #FFAD33; -webkit-border-radius: 5px; -webkit-box-shadow: 5px 5px rgba(0, 0, 0, 0.1); position: absolute; left: 1em; top: 2em; z-index: 99; margin-left: 0; width: 250px;"><b>Some info 3</b><ul><li>test 1</li><li>test 2</li></ul></span>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
    
<a style="border-bottom: 1px dotted #000000; color: #000000; outline: none; cursor: help; text-decoration: none; position: relative;" href="#">(Info 4)</a>
<span style="visibility: hidden; color: #000000; cursor: help; padding: 0.8em 1em; background: #FFFFAA; border: 1px solid #FFAD33; -webkit-border-radius: 5px; -webkit-box-shadow: 5px 5px rgba(0, 0, 0, 0.1); position: absolute; left: 1em; top: 2em; z-index: 99; margin-left: 0; width: 250px;"><b>Some info 4</b><ul><li>test 1</li><li>test 2</li></ul></span>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>