Tooltip-overlay following the mouse pointer












2















The purpose is to attach a tooltip-element to arbitrary HTML-elements.



The tooltip appears when the user hovers an element. Follows the mouse-pointer while moving over the element.






/**
* Attaches a tooltip to every element in the result-set.

* @param { string } selector - An CSS-selector.
* @param { number } horizontalOffset - Horizontal
* distance to the mouse pointer.
* @param { number } VerticalOffset - Vertical distance
* to the mouse pointer.
*
* All parameter are optional. But providing a valid
* selector is indispensable for the function to work.
*
* Usage example:
* ... })('.tooltip-item', 10, 5);
*/
(function(selector, horizontalOffset, verticalOffset) {
var items;

selector = selector || '.tooltip';
horizontalOffset = horizontalOffset || 5;
verticalOffset = verticalOffset || 5;

items = document.querySelectorAll(selector);
items = Array.prototype.slice.call(items);

items.forEach(function(item) {
// Every time the pointer moves over the element the
// CSS-rule in overwritten with new values for
// top and left.
item.addEventListener('mousemove', function(e) {
let countCssRules = document.styleSheets[0].cssRules.length;
let newRule = selector +
':hover:after { display: block; ' +
'left: ' + (e.offsetX + horizontalOffset) + 'px; ' +
'top: ' + (e.offsetY + verticalOffset) + 'px; }';

document.styleSheets[0].insertRule(newRule, countCssRules);
});
});
})('.tooltip-item', 10, 5);

.wrap {
width: 1000px;
margin: 50px auto;
font-family: georgia, serif;
background-color: cornsilk;
padding: 20px 30px;
}

div.tooltip-item {
background-color: orange;
width: 450px;
height: 100px;
border: 1px solid black;
border-radius: 8px;
margin: 60px 10px;
}

.tooltip-item {
position: relative;
cursor: pointer;
}

.tooltip-item:after {
content: attr(data-message);
position: absolute;
left: 105%;
white-space: nowrap;
display: none;
font-size: 1.2rem;
background-color: rgba(230, 230, 230, 0.6);
padding: 10px 20px;
border-radius: 16px;
font-family: Tahoma, Verdana, Segoe, sans-serif;
font-weight: normal;
}

div.tooltip-item:after {
text-transform: uppercase;
}

h1.tooltip-item:after {
background-color: cyan;
color: #ff14ec;
font-weight: 800;
border-radius: 20px;
box-shadow: 6px 6px 9px #969696;
}

p.tooltip-item:after {
background-color: #232323;
color: #efefef;
font-weight: 800;
border-radius: 6px;
box-shadow: 0 0 0 grey;
}

<div class="wrap">
<h1 class="tooltip-item" data-message="You are hovering the h1-element.">Demo Page - Tooltip following the Mouse-Pointer</h1>
<div class="tooltip-item" data-message="Lorem ipsum dolor sit amet, consectetuer adipiscing elit."></div>
<p class="tooltip-item" data-message="Paragraph-element with a tooltip attached to it.">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.</p>
</div>





The uncompiled Sass-code:






$fontStack: Tahoma, Verdana, Segoe, sans-serif;
$primaryColor: cornsilk;

@function getGreyValue($greyByte: 240, $opacity: 1.0) {
@return rgba($greyByte, $greyByte, $greyByte, $opacity);
}

@mixin setTooltipStyles( $element,
$backgroundColor: #232323,
$color: #efefef,
$fontWeight: 600,
$borderRadius: 6px,
$shadowX: 0,
$shadowY: 0,
$shadowBlur: 0,
$shadowColor: grey ) {
#{ $element }.tooltip-item:after {
background-color: $backgroundColor;
color: $color;
font-weight: 800;
border-radius: $borderRadius;
box-shadow: $shadowX $shadowY $shadowBlur $shadowColor;
}
}

.wrap {
width: 1000px;
margin: 50px auto;
font-family: georgia, serif;
background-color: $primaryColor;
padding: 20px 30px;
}

div.tooltip-item {
background-color: orange;
width: 450px;
height: 100px;
border: 1px solid black;
border-radius: 8px;
margin: 60px 10px;
}

.tooltip-item {
position: relative; // Essential for tooltip to work!
cursor: pointer;
}

.tooltip-item:after {
content: attr(data-message); // Essential for tooltip to work!
position: absolute; // Essential for tooltip to work!
left: 105%;
white-space: nowrap;
display: none;
font-size: 1.2rem;
background-color: getGreyValue(230, 0.6);
padding: 10px 20px;
border-radius: 16px;
font-family: $fontStack;
font-weight: normal;
}
// Use higher specificity for getting different designs.
div.tooltip-item:after {
text-transform: uppercase;
}

@include setTooltipStyles('h1', cyan, #ff14ec, 800, 20px, 6px, 6px, 9px, rgba(150, 150, 150, 1.0));


@include setTooltipStyles('p');





Currently it is necessary to write certain mandatory code in HTML and CSS. Afterwards the JavaScript function can be used.



Should I try to concentrate more on JavaScript only? I mean: Should I try to reduce the mandatory HTML-, CSS-code to a minimun?



Or is Okay the way I have done it?



The parameter of the JavaScript-function are optional.



But actually the first parameter (CSS-selector) is mandatory for the function to work. If it isn't correct to code will silently fail.



Should I change that?



Return with an exit-code which signals an error? Perhaps even throw an exception?



Looking forward to read your opions about the points I have mentioned. Other hints would interest me too.










share|improve this question



























    2















    The purpose is to attach a tooltip-element to arbitrary HTML-elements.



    The tooltip appears when the user hovers an element. Follows the mouse-pointer while moving over the element.






    /**
    * Attaches a tooltip to every element in the result-set.

    * @param { string } selector - An CSS-selector.
    * @param { number } horizontalOffset - Horizontal
    * distance to the mouse pointer.
    * @param { number } VerticalOffset - Vertical distance
    * to the mouse pointer.
    *
    * All parameter are optional. But providing a valid
    * selector is indispensable for the function to work.
    *
    * Usage example:
    * ... })('.tooltip-item', 10, 5);
    */
    (function(selector, horizontalOffset, verticalOffset) {
    var items;

    selector = selector || '.tooltip';
    horizontalOffset = horizontalOffset || 5;
    verticalOffset = verticalOffset || 5;

    items = document.querySelectorAll(selector);
    items = Array.prototype.slice.call(items);

    items.forEach(function(item) {
    // Every time the pointer moves over the element the
    // CSS-rule in overwritten with new values for
    // top and left.
    item.addEventListener('mousemove', function(e) {
    let countCssRules = document.styleSheets[0].cssRules.length;
    let newRule = selector +
    ':hover:after { display: block; ' +
    'left: ' + (e.offsetX + horizontalOffset) + 'px; ' +
    'top: ' + (e.offsetY + verticalOffset) + 'px; }';

    document.styleSheets[0].insertRule(newRule, countCssRules);
    });
    });
    })('.tooltip-item', 10, 5);

    .wrap {
    width: 1000px;
    margin: 50px auto;
    font-family: georgia, serif;
    background-color: cornsilk;
    padding: 20px 30px;
    }

    div.tooltip-item {
    background-color: orange;
    width: 450px;
    height: 100px;
    border: 1px solid black;
    border-radius: 8px;
    margin: 60px 10px;
    }

    .tooltip-item {
    position: relative;
    cursor: pointer;
    }

    .tooltip-item:after {
    content: attr(data-message);
    position: absolute;
    left: 105%;
    white-space: nowrap;
    display: none;
    font-size: 1.2rem;
    background-color: rgba(230, 230, 230, 0.6);
    padding: 10px 20px;
    border-radius: 16px;
    font-family: Tahoma, Verdana, Segoe, sans-serif;
    font-weight: normal;
    }

    div.tooltip-item:after {
    text-transform: uppercase;
    }

    h1.tooltip-item:after {
    background-color: cyan;
    color: #ff14ec;
    font-weight: 800;
    border-radius: 20px;
    box-shadow: 6px 6px 9px #969696;
    }

    p.tooltip-item:after {
    background-color: #232323;
    color: #efefef;
    font-weight: 800;
    border-radius: 6px;
    box-shadow: 0 0 0 grey;
    }

    <div class="wrap">
    <h1 class="tooltip-item" data-message="You are hovering the h1-element.">Demo Page - Tooltip following the Mouse-Pointer</h1>
    <div class="tooltip-item" data-message="Lorem ipsum dolor sit amet, consectetuer adipiscing elit."></div>
    <p class="tooltip-item" data-message="Paragraph-element with a tooltip attached to it.">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.</p>
    </div>





    The uncompiled Sass-code:






    $fontStack: Tahoma, Verdana, Segoe, sans-serif;
    $primaryColor: cornsilk;

    @function getGreyValue($greyByte: 240, $opacity: 1.0) {
    @return rgba($greyByte, $greyByte, $greyByte, $opacity);
    }

    @mixin setTooltipStyles( $element,
    $backgroundColor: #232323,
    $color: #efefef,
    $fontWeight: 600,
    $borderRadius: 6px,
    $shadowX: 0,
    $shadowY: 0,
    $shadowBlur: 0,
    $shadowColor: grey ) {
    #{ $element }.tooltip-item:after {
    background-color: $backgroundColor;
    color: $color;
    font-weight: 800;
    border-radius: $borderRadius;
    box-shadow: $shadowX $shadowY $shadowBlur $shadowColor;
    }
    }

    .wrap {
    width: 1000px;
    margin: 50px auto;
    font-family: georgia, serif;
    background-color: $primaryColor;
    padding: 20px 30px;
    }

    div.tooltip-item {
    background-color: orange;
    width: 450px;
    height: 100px;
    border: 1px solid black;
    border-radius: 8px;
    margin: 60px 10px;
    }

    .tooltip-item {
    position: relative; // Essential for tooltip to work!
    cursor: pointer;
    }

    .tooltip-item:after {
    content: attr(data-message); // Essential for tooltip to work!
    position: absolute; // Essential for tooltip to work!
    left: 105%;
    white-space: nowrap;
    display: none;
    font-size: 1.2rem;
    background-color: getGreyValue(230, 0.6);
    padding: 10px 20px;
    border-radius: 16px;
    font-family: $fontStack;
    font-weight: normal;
    }
    // Use higher specificity for getting different designs.
    div.tooltip-item:after {
    text-transform: uppercase;
    }

    @include setTooltipStyles('h1', cyan, #ff14ec, 800, 20px, 6px, 6px, 9px, rgba(150, 150, 150, 1.0));


    @include setTooltipStyles('p');





    Currently it is necessary to write certain mandatory code in HTML and CSS. Afterwards the JavaScript function can be used.



    Should I try to concentrate more on JavaScript only? I mean: Should I try to reduce the mandatory HTML-, CSS-code to a minimun?



    Or is Okay the way I have done it?



    The parameter of the JavaScript-function are optional.



    But actually the first parameter (CSS-selector) is mandatory for the function to work. If it isn't correct to code will silently fail.



    Should I change that?



    Return with an exit-code which signals an error? Perhaps even throw an exception?



    Looking forward to read your opions about the points I have mentioned. Other hints would interest me too.










    share|improve this question

























      2












      2








      2








      The purpose is to attach a tooltip-element to arbitrary HTML-elements.



      The tooltip appears when the user hovers an element. Follows the mouse-pointer while moving over the element.






      /**
      * Attaches a tooltip to every element in the result-set.

      * @param { string } selector - An CSS-selector.
      * @param { number } horizontalOffset - Horizontal
      * distance to the mouse pointer.
      * @param { number } VerticalOffset - Vertical distance
      * to the mouse pointer.
      *
      * All parameter are optional. But providing a valid
      * selector is indispensable for the function to work.
      *
      * Usage example:
      * ... })('.tooltip-item', 10, 5);
      */
      (function(selector, horizontalOffset, verticalOffset) {
      var items;

      selector = selector || '.tooltip';
      horizontalOffset = horizontalOffset || 5;
      verticalOffset = verticalOffset || 5;

      items = document.querySelectorAll(selector);
      items = Array.prototype.slice.call(items);

      items.forEach(function(item) {
      // Every time the pointer moves over the element the
      // CSS-rule in overwritten with new values for
      // top and left.
      item.addEventListener('mousemove', function(e) {
      let countCssRules = document.styleSheets[0].cssRules.length;
      let newRule = selector +
      ':hover:after { display: block; ' +
      'left: ' + (e.offsetX + horizontalOffset) + 'px; ' +
      'top: ' + (e.offsetY + verticalOffset) + 'px; }';

      document.styleSheets[0].insertRule(newRule, countCssRules);
      });
      });
      })('.tooltip-item', 10, 5);

      .wrap {
      width: 1000px;
      margin: 50px auto;
      font-family: georgia, serif;
      background-color: cornsilk;
      padding: 20px 30px;
      }

      div.tooltip-item {
      background-color: orange;
      width: 450px;
      height: 100px;
      border: 1px solid black;
      border-radius: 8px;
      margin: 60px 10px;
      }

      .tooltip-item {
      position: relative;
      cursor: pointer;
      }

      .tooltip-item:after {
      content: attr(data-message);
      position: absolute;
      left: 105%;
      white-space: nowrap;
      display: none;
      font-size: 1.2rem;
      background-color: rgba(230, 230, 230, 0.6);
      padding: 10px 20px;
      border-radius: 16px;
      font-family: Tahoma, Verdana, Segoe, sans-serif;
      font-weight: normal;
      }

      div.tooltip-item:after {
      text-transform: uppercase;
      }

      h1.tooltip-item:after {
      background-color: cyan;
      color: #ff14ec;
      font-weight: 800;
      border-radius: 20px;
      box-shadow: 6px 6px 9px #969696;
      }

      p.tooltip-item:after {
      background-color: #232323;
      color: #efefef;
      font-weight: 800;
      border-radius: 6px;
      box-shadow: 0 0 0 grey;
      }

      <div class="wrap">
      <h1 class="tooltip-item" data-message="You are hovering the h1-element.">Demo Page - Tooltip following the Mouse-Pointer</h1>
      <div class="tooltip-item" data-message="Lorem ipsum dolor sit amet, consectetuer adipiscing elit."></div>
      <p class="tooltip-item" data-message="Paragraph-element with a tooltip attached to it.">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.</p>
      </div>





      The uncompiled Sass-code:






      $fontStack: Tahoma, Verdana, Segoe, sans-serif;
      $primaryColor: cornsilk;

      @function getGreyValue($greyByte: 240, $opacity: 1.0) {
      @return rgba($greyByte, $greyByte, $greyByte, $opacity);
      }

      @mixin setTooltipStyles( $element,
      $backgroundColor: #232323,
      $color: #efefef,
      $fontWeight: 600,
      $borderRadius: 6px,
      $shadowX: 0,
      $shadowY: 0,
      $shadowBlur: 0,
      $shadowColor: grey ) {
      #{ $element }.tooltip-item:after {
      background-color: $backgroundColor;
      color: $color;
      font-weight: 800;
      border-radius: $borderRadius;
      box-shadow: $shadowX $shadowY $shadowBlur $shadowColor;
      }
      }

      .wrap {
      width: 1000px;
      margin: 50px auto;
      font-family: georgia, serif;
      background-color: $primaryColor;
      padding: 20px 30px;
      }

      div.tooltip-item {
      background-color: orange;
      width: 450px;
      height: 100px;
      border: 1px solid black;
      border-radius: 8px;
      margin: 60px 10px;
      }

      .tooltip-item {
      position: relative; // Essential for tooltip to work!
      cursor: pointer;
      }

      .tooltip-item:after {
      content: attr(data-message); // Essential for tooltip to work!
      position: absolute; // Essential for tooltip to work!
      left: 105%;
      white-space: nowrap;
      display: none;
      font-size: 1.2rem;
      background-color: getGreyValue(230, 0.6);
      padding: 10px 20px;
      border-radius: 16px;
      font-family: $fontStack;
      font-weight: normal;
      }
      // Use higher specificity for getting different designs.
      div.tooltip-item:after {
      text-transform: uppercase;
      }

      @include setTooltipStyles('h1', cyan, #ff14ec, 800, 20px, 6px, 6px, 9px, rgba(150, 150, 150, 1.0));


      @include setTooltipStyles('p');





      Currently it is necessary to write certain mandatory code in HTML and CSS. Afterwards the JavaScript function can be used.



      Should I try to concentrate more on JavaScript only? I mean: Should I try to reduce the mandatory HTML-, CSS-code to a minimun?



      Or is Okay the way I have done it?



      The parameter of the JavaScript-function are optional.



      But actually the first parameter (CSS-selector) is mandatory for the function to work. If it isn't correct to code will silently fail.



      Should I change that?



      Return with an exit-code which signals an error? Perhaps even throw an exception?



      Looking forward to read your opions about the points I have mentioned. Other hints would interest me too.










      share|improve this question














      The purpose is to attach a tooltip-element to arbitrary HTML-elements.



      The tooltip appears when the user hovers an element. Follows the mouse-pointer while moving over the element.






      /**
      * Attaches a tooltip to every element in the result-set.

      * @param { string } selector - An CSS-selector.
      * @param { number } horizontalOffset - Horizontal
      * distance to the mouse pointer.
      * @param { number } VerticalOffset - Vertical distance
      * to the mouse pointer.
      *
      * All parameter are optional. But providing a valid
      * selector is indispensable for the function to work.
      *
      * Usage example:
      * ... })('.tooltip-item', 10, 5);
      */
      (function(selector, horizontalOffset, verticalOffset) {
      var items;

      selector = selector || '.tooltip';
      horizontalOffset = horizontalOffset || 5;
      verticalOffset = verticalOffset || 5;

      items = document.querySelectorAll(selector);
      items = Array.prototype.slice.call(items);

      items.forEach(function(item) {
      // Every time the pointer moves over the element the
      // CSS-rule in overwritten with new values for
      // top and left.
      item.addEventListener('mousemove', function(e) {
      let countCssRules = document.styleSheets[0].cssRules.length;
      let newRule = selector +
      ':hover:after { display: block; ' +
      'left: ' + (e.offsetX + horizontalOffset) + 'px; ' +
      'top: ' + (e.offsetY + verticalOffset) + 'px; }';

      document.styleSheets[0].insertRule(newRule, countCssRules);
      });
      });
      })('.tooltip-item', 10, 5);

      .wrap {
      width: 1000px;
      margin: 50px auto;
      font-family: georgia, serif;
      background-color: cornsilk;
      padding: 20px 30px;
      }

      div.tooltip-item {
      background-color: orange;
      width: 450px;
      height: 100px;
      border: 1px solid black;
      border-radius: 8px;
      margin: 60px 10px;
      }

      .tooltip-item {
      position: relative;
      cursor: pointer;
      }

      .tooltip-item:after {
      content: attr(data-message);
      position: absolute;
      left: 105%;
      white-space: nowrap;
      display: none;
      font-size: 1.2rem;
      background-color: rgba(230, 230, 230, 0.6);
      padding: 10px 20px;
      border-radius: 16px;
      font-family: Tahoma, Verdana, Segoe, sans-serif;
      font-weight: normal;
      }

      div.tooltip-item:after {
      text-transform: uppercase;
      }

      h1.tooltip-item:after {
      background-color: cyan;
      color: #ff14ec;
      font-weight: 800;
      border-radius: 20px;
      box-shadow: 6px 6px 9px #969696;
      }

      p.tooltip-item:after {
      background-color: #232323;
      color: #efefef;
      font-weight: 800;
      border-radius: 6px;
      box-shadow: 0 0 0 grey;
      }

      <div class="wrap">
      <h1 class="tooltip-item" data-message="You are hovering the h1-element.">Demo Page - Tooltip following the Mouse-Pointer</h1>
      <div class="tooltip-item" data-message="Lorem ipsum dolor sit amet, consectetuer adipiscing elit."></div>
      <p class="tooltip-item" data-message="Paragraph-element with a tooltip attached to it.">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.</p>
      </div>





      The uncompiled Sass-code:






      $fontStack: Tahoma, Verdana, Segoe, sans-serif;
      $primaryColor: cornsilk;

      @function getGreyValue($greyByte: 240, $opacity: 1.0) {
      @return rgba($greyByte, $greyByte, $greyByte, $opacity);
      }

      @mixin setTooltipStyles( $element,
      $backgroundColor: #232323,
      $color: #efefef,
      $fontWeight: 600,
      $borderRadius: 6px,
      $shadowX: 0,
      $shadowY: 0,
      $shadowBlur: 0,
      $shadowColor: grey ) {
      #{ $element }.tooltip-item:after {
      background-color: $backgroundColor;
      color: $color;
      font-weight: 800;
      border-radius: $borderRadius;
      box-shadow: $shadowX $shadowY $shadowBlur $shadowColor;
      }
      }

      .wrap {
      width: 1000px;
      margin: 50px auto;
      font-family: georgia, serif;
      background-color: $primaryColor;
      padding: 20px 30px;
      }

      div.tooltip-item {
      background-color: orange;
      width: 450px;
      height: 100px;
      border: 1px solid black;
      border-radius: 8px;
      margin: 60px 10px;
      }

      .tooltip-item {
      position: relative; // Essential for tooltip to work!
      cursor: pointer;
      }

      .tooltip-item:after {
      content: attr(data-message); // Essential for tooltip to work!
      position: absolute; // Essential for tooltip to work!
      left: 105%;
      white-space: nowrap;
      display: none;
      font-size: 1.2rem;
      background-color: getGreyValue(230, 0.6);
      padding: 10px 20px;
      border-radius: 16px;
      font-family: $fontStack;
      font-weight: normal;
      }
      // Use higher specificity for getting different designs.
      div.tooltip-item:after {
      text-transform: uppercase;
      }

      @include setTooltipStyles('h1', cyan, #ff14ec, 800, 20px, 6px, 6px, 9px, rgba(150, 150, 150, 1.0));


      @include setTooltipStyles('p');





      Currently it is necessary to write certain mandatory code in HTML and CSS. Afterwards the JavaScript function can be used.



      Should I try to concentrate more on JavaScript only? I mean: Should I try to reduce the mandatory HTML-, CSS-code to a minimun?



      Or is Okay the way I have done it?



      The parameter of the JavaScript-function are optional.



      But actually the first parameter (CSS-selector) is mandatory for the function to work. If it isn't correct to code will silently fail.



      Should I change that?



      Return with an exit-code which signals an error? Perhaps even throw an exception?



      Looking forward to read your opions about the points I have mentioned. Other hints would interest me too.






      /**
      * Attaches a tooltip to every element in the result-set.

      * @param { string } selector - An CSS-selector.
      * @param { number } horizontalOffset - Horizontal
      * distance to the mouse pointer.
      * @param { number } VerticalOffset - Vertical distance
      * to the mouse pointer.
      *
      * All parameter are optional. But providing a valid
      * selector is indispensable for the function to work.
      *
      * Usage example:
      * ... })('.tooltip-item', 10, 5);
      */
      (function(selector, horizontalOffset, verticalOffset) {
      var items;

      selector = selector || '.tooltip';
      horizontalOffset = horizontalOffset || 5;
      verticalOffset = verticalOffset || 5;

      items = document.querySelectorAll(selector);
      items = Array.prototype.slice.call(items);

      items.forEach(function(item) {
      // Every time the pointer moves over the element the
      // CSS-rule in overwritten with new values for
      // top and left.
      item.addEventListener('mousemove', function(e) {
      let countCssRules = document.styleSheets[0].cssRules.length;
      let newRule = selector +
      ':hover:after { display: block; ' +
      'left: ' + (e.offsetX + horizontalOffset) + 'px; ' +
      'top: ' + (e.offsetY + verticalOffset) + 'px; }';

      document.styleSheets[0].insertRule(newRule, countCssRules);
      });
      });
      })('.tooltip-item', 10, 5);

      .wrap {
      width: 1000px;
      margin: 50px auto;
      font-family: georgia, serif;
      background-color: cornsilk;
      padding: 20px 30px;
      }

      div.tooltip-item {
      background-color: orange;
      width: 450px;
      height: 100px;
      border: 1px solid black;
      border-radius: 8px;
      margin: 60px 10px;
      }

      .tooltip-item {
      position: relative;
      cursor: pointer;
      }

      .tooltip-item:after {
      content: attr(data-message);
      position: absolute;
      left: 105%;
      white-space: nowrap;
      display: none;
      font-size: 1.2rem;
      background-color: rgba(230, 230, 230, 0.6);
      padding: 10px 20px;
      border-radius: 16px;
      font-family: Tahoma, Verdana, Segoe, sans-serif;
      font-weight: normal;
      }

      div.tooltip-item:after {
      text-transform: uppercase;
      }

      h1.tooltip-item:after {
      background-color: cyan;
      color: #ff14ec;
      font-weight: 800;
      border-radius: 20px;
      box-shadow: 6px 6px 9px #969696;
      }

      p.tooltip-item:after {
      background-color: #232323;
      color: #efefef;
      font-weight: 800;
      border-radius: 6px;
      box-shadow: 0 0 0 grey;
      }

      <div class="wrap">
      <h1 class="tooltip-item" data-message="You are hovering the h1-element.">Demo Page - Tooltip following the Mouse-Pointer</h1>
      <div class="tooltip-item" data-message="Lorem ipsum dolor sit amet, consectetuer adipiscing elit."></div>
      <p class="tooltip-item" data-message="Paragraph-element with a tooltip attached to it.">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.</p>
      </div>





      /**
      * Attaches a tooltip to every element in the result-set.

      * @param { string } selector - An CSS-selector.
      * @param { number } horizontalOffset - Horizontal
      * distance to the mouse pointer.
      * @param { number } VerticalOffset - Vertical distance
      * to the mouse pointer.
      *
      * All parameter are optional. But providing a valid
      * selector is indispensable for the function to work.
      *
      * Usage example:
      * ... })('.tooltip-item', 10, 5);
      */
      (function(selector, horizontalOffset, verticalOffset) {
      var items;

      selector = selector || '.tooltip';
      horizontalOffset = horizontalOffset || 5;
      verticalOffset = verticalOffset || 5;

      items = document.querySelectorAll(selector);
      items = Array.prototype.slice.call(items);

      items.forEach(function(item) {
      // Every time the pointer moves over the element the
      // CSS-rule in overwritten with new values for
      // top and left.
      item.addEventListener('mousemove', function(e) {
      let countCssRules = document.styleSheets[0].cssRules.length;
      let newRule = selector +
      ':hover:after { display: block; ' +
      'left: ' + (e.offsetX + horizontalOffset) + 'px; ' +
      'top: ' + (e.offsetY + verticalOffset) + 'px; }';

      document.styleSheets[0].insertRule(newRule, countCssRules);
      });
      });
      })('.tooltip-item', 10, 5);

      .wrap {
      width: 1000px;
      margin: 50px auto;
      font-family: georgia, serif;
      background-color: cornsilk;
      padding: 20px 30px;
      }

      div.tooltip-item {
      background-color: orange;
      width: 450px;
      height: 100px;
      border: 1px solid black;
      border-radius: 8px;
      margin: 60px 10px;
      }

      .tooltip-item {
      position: relative;
      cursor: pointer;
      }

      .tooltip-item:after {
      content: attr(data-message);
      position: absolute;
      left: 105%;
      white-space: nowrap;
      display: none;
      font-size: 1.2rem;
      background-color: rgba(230, 230, 230, 0.6);
      padding: 10px 20px;
      border-radius: 16px;
      font-family: Tahoma, Verdana, Segoe, sans-serif;
      font-weight: normal;
      }

      div.tooltip-item:after {
      text-transform: uppercase;
      }

      h1.tooltip-item:after {
      background-color: cyan;
      color: #ff14ec;
      font-weight: 800;
      border-radius: 20px;
      box-shadow: 6px 6px 9px #969696;
      }

      p.tooltip-item:after {
      background-color: #232323;
      color: #efefef;
      font-weight: 800;
      border-radius: 6px;
      box-shadow: 0 0 0 grey;
      }

      <div class="wrap">
      <h1 class="tooltip-item" data-message="You are hovering the h1-element.">Demo Page - Tooltip following the Mouse-Pointer</h1>
      <div class="tooltip-item" data-message="Lorem ipsum dolor sit amet, consectetuer adipiscing elit."></div>
      <p class="tooltip-item" data-message="Paragraph-element with a tooltip attached to it.">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.</p>
      </div>





      $fontStack: Tahoma, Verdana, Segoe, sans-serif;
      $primaryColor: cornsilk;

      @function getGreyValue($greyByte: 240, $opacity: 1.0) {
      @return rgba($greyByte, $greyByte, $greyByte, $opacity);
      }

      @mixin setTooltipStyles( $element,
      $backgroundColor: #232323,
      $color: #efefef,
      $fontWeight: 600,
      $borderRadius: 6px,
      $shadowX: 0,
      $shadowY: 0,
      $shadowBlur: 0,
      $shadowColor: grey ) {
      #{ $element }.tooltip-item:after {
      background-color: $backgroundColor;
      color: $color;
      font-weight: 800;
      border-radius: $borderRadius;
      box-shadow: $shadowX $shadowY $shadowBlur $shadowColor;
      }
      }

      .wrap {
      width: 1000px;
      margin: 50px auto;
      font-family: georgia, serif;
      background-color: $primaryColor;
      padding: 20px 30px;
      }

      div.tooltip-item {
      background-color: orange;
      width: 450px;
      height: 100px;
      border: 1px solid black;
      border-radius: 8px;
      margin: 60px 10px;
      }

      .tooltip-item {
      position: relative; // Essential for tooltip to work!
      cursor: pointer;
      }

      .tooltip-item:after {
      content: attr(data-message); // Essential for tooltip to work!
      position: absolute; // Essential for tooltip to work!
      left: 105%;
      white-space: nowrap;
      display: none;
      font-size: 1.2rem;
      background-color: getGreyValue(230, 0.6);
      padding: 10px 20px;
      border-radius: 16px;
      font-family: $fontStack;
      font-weight: normal;
      }
      // Use higher specificity for getting different designs.
      div.tooltip-item:after {
      text-transform: uppercase;
      }

      @include setTooltipStyles('h1', cyan, #ff14ec, 800, 20px, 6px, 6px, 9px, rgba(150, 150, 150, 1.0));


      @include setTooltipStyles('p');





      $fontStack: Tahoma, Verdana, Segoe, sans-serif;
      $primaryColor: cornsilk;

      @function getGreyValue($greyByte: 240, $opacity: 1.0) {
      @return rgba($greyByte, $greyByte, $greyByte, $opacity);
      }

      @mixin setTooltipStyles( $element,
      $backgroundColor: #232323,
      $color: #efefef,
      $fontWeight: 600,
      $borderRadius: 6px,
      $shadowX: 0,
      $shadowY: 0,
      $shadowBlur: 0,
      $shadowColor: grey ) {
      #{ $element }.tooltip-item:after {
      background-color: $backgroundColor;
      color: $color;
      font-weight: 800;
      border-radius: $borderRadius;
      box-shadow: $shadowX $shadowY $shadowBlur $shadowColor;
      }
      }

      .wrap {
      width: 1000px;
      margin: 50px auto;
      font-family: georgia, serif;
      background-color: $primaryColor;
      padding: 20px 30px;
      }

      div.tooltip-item {
      background-color: orange;
      width: 450px;
      height: 100px;
      border: 1px solid black;
      border-radius: 8px;
      margin: 60px 10px;
      }

      .tooltip-item {
      position: relative; // Essential for tooltip to work!
      cursor: pointer;
      }

      .tooltip-item:after {
      content: attr(data-message); // Essential for tooltip to work!
      position: absolute; // Essential for tooltip to work!
      left: 105%;
      white-space: nowrap;
      display: none;
      font-size: 1.2rem;
      background-color: getGreyValue(230, 0.6);
      padding: 10px 20px;
      border-radius: 16px;
      font-family: $fontStack;
      font-weight: normal;
      }
      // Use higher specificity for getting different designs.
      div.tooltip-item:after {
      text-transform: uppercase;
      }

      @include setTooltipStyles('h1', cyan, #ff14ec, 800, 20px, 6px, 6px, 9px, rgba(150, 150, 150, 1.0));


      @include setTooltipStyles('p');






      javascript css sass






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Aug 22 '16 at 5:53









      michael.zechmichael.zech

      1,7161633




      1,7161633






















          2 Answers
          2






          active

          oldest

          votes


















          2















          Should I try to concentrate more on JavaScript only? I mean: Should I try to reduce the mandatory HTML-, CSS-code to a minimun?




          I think, the code i.e. HTML and CSS are minimal. Storing the tooltip on the HTML elements is correct way rather than storing it in JavaScript. So, NO. You should not only concentrate on JavaScript.




          Or is Okay the way I have done it?




          Yes, the logic is correct. However, the code can be shortened(see below) when written in ES6.




          But actually the first parameter (CSS-selector) is mandatory for the function to work. If it isn't correct to code will silently fail.



          Should I change that?



          Return with an exit-code which signals an error? Perhaps even throw an exception?




          Let's look at the following statement



          selector = selector || '.tooltip';


          This means, if selector is falsy, selector will be .tooltip. So, there will be no case when the selector will be empty and error will be thrown. That means, there is no need to handle that error.



          And, I'll also suggest to use [data-message] as default parameter. This will select all the elements having data-message attribute.





          Here are some suggestions:



          As let is used either the environment you're using supports ES6 or the source files are compiled to ES5.



          Following features of ES6 can be used





          1. Default Parameters



            This will allow to use the assigned value to the parameter as default value if no value is passed when invoking the function.



            Now, ES5's default parameter notation



            selector = selector || '.tooltip';


            is no longer needed.




          2. Array.from()



            Array.from() can be used to create an array from array-like structures. To iterate over the DOM elements selected by querySelectorAll(), Array.from() can be used.



            items = document.querySelectorAll(selector);
            items = Array.prototype.slice.call(items);

            items.forEach(function(item) {


            can be written as



            Array.from(document.querySelectorAll(selector))
            .forEach(function (item) {



          Updated Code:






          (function (selector = '[data-message]', horizontalOffset = 5, verticalOffset = 5) {
          'use strict';

          Array.from(document.querySelectorAll(selector)).forEach(function (item) {
          // Every time the pointer moves over the element the
          // CSS-rule in overwritten with new values for
          // top and left.
          item.addEventListener('mousemove', function (e) {
          let countCssRules = document.styleSheets[0].cssRules.length;
          let newRule = selector +
          ':hover:after { display: block; ' +
          'left: ' + (e.offsetX + horizontalOffset) + 'px; ' +
          'top: ' + (e.offsetY + verticalOffset) + 'px; }';

          document.styleSheets[0].insertRule(newRule, countCssRules);
          });
          });
          }('.tooltip-item', 10));

          .wrap {
          width: 1000px;
          margin: 50px auto;
          font-family: georgia, serif;
          background-color: cornsilk;
          padding: 20px 30px;
          }

          div.tooltip-item {
          background-color: orange;
          width: 450px;
          height: 100px;
          border: 1px solid black;
          border-radius: 8px;
          margin: 60px 10px;
          }

          .tooltip-item {
          position: relative;
          cursor: pointer;
          }

          .tooltip-item:after {
          content: attr(data-message);
          position: absolute;
          left: 105%;
          white-space: nowrap;
          display: none;
          font-size: 1.2rem;
          background-color: rgba(230, 230, 230, 0.6);
          padding: 10px 20px;
          border-radius: 16px;
          font-family: Tahoma, Verdana, Segoe, sans-serif;
          font-weight: normal;
          }

          div.tooltip-item:after {
          text-transform: uppercase;
          }

          h1.tooltip-item:after {
          background-color: cyan;
          color: #ff14ec;
          font-weight: 800;
          border-radius: 20px;
          box-shadow: 6px 6px 9px #969696;
          }

          p.tooltip-item:after {
          background-color: #232323;
          color: #efefef;
          font-weight: 800;
          border-radius: 6px;
          box-shadow: 0 0 0 grey;
          }

          <div class="wrap">
          <h1 class="tooltip-item" data-message="You are hovering the h1-element.">Demo Page - Tooltip following the Mouse-Pointer</h1>
          <div class="tooltip-item" data-message="Lorem ipsum dolor sit amet, consectetuer adipiscing elit."></div>
          <p class="tooltip-item" data-message="Paragraph-element with a tooltip attached to it.">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.</p>
          </div>








          share|improve this answer































            0














            I found this post and took your code and made some changes. I wanted to have a very small piece of javascript code that supported style-able tooltips.



            First, the way you were editing the CSS was to add an additional style every time the mouse moves. This will create hundreds of style additions in just a few seconds of mouse movement, so very inefficient over time. To avoid this, I created a blank style for the hover class and preserved reference to this style definition. I then modified the style using this reference, rather than creating new styles every time the handler is called.



            Second, the code doesn't account for if the value is blank. The tooltip will show a blank box, instead of not showing at all. So I added a conditional to hide the tooltip if this is case.



            Third, you can select a CSS style by data attribute, so there is no need to specify a .tooltip class for the element. So I dropped that.



            Forth, setting the position of the tooltip element relative to the hover element has glitches. If the hover element is inside another element, the tooltip width will be glitchy and often too narrow if the parent element is something small, like a table cell. There are workarounds, such as setting a fixed width of the tooltip element, but this isn't ideal. There is another workaround to contain the tooltip in a wrapper div, but you cannot do this because html is not allowed when using the CSS content attribute. The fix I used is to set the tooltip to "display: fixed", and set position based on screen coordinates. This allows me to use max-width while shorter tooltips are only the width of the text.



            A final note: this solution is probably not ideal on a mobile device. But I am using this for a desktop environment, so it works for this class of usage.






            document.addEventListener('DOMContentLoaded', function() {
            var cssSheet = document.styleSheets[0];
            var hoverIndex = cssSheet.insertRule('[data-tooltip]:hover:after {}', cssSheet.cssRules.length);
            var cssHover = cssSheet.cssRules[hoverIndex];
            Array.from(document.querySelectorAll('[data-tooltip]')).forEach(function (item) {
            item.addEventListener('mousemove', function (e) {
            if (this.dataset.tooltip == '') {
            cssHover.style.display = 'none';
            return;
            }
            cssHover.style.display = 'block';
            cssHover.style.left = (e.clientX + 15) + 'px';
            cssHover.style.top = (e.clientY + 15) + 'px';
            });
            });
            });

            [data-tooltip] {
            border-bottom: 1px dotted #777;
            cursor: help;
            }

            [data-tooltip]:after {
            content: attr(data-tooltip);
            display: none;
            position: fixed;
            max-width: 600px;
            background: #ffd;
            border: 1px solid #999;
            padding: 12px;
            color: #000;
            border-radius: 3px;
            margin: 0;
            font-size: 14px;

            left: 50px;
            top:25px;
            z-index: 10;

            box-shadow: 0px 0px 5px rgba(0,0,0,.2);

            line-height: 1.3em;
            }

            <p><span data-tooltip='I am a tooltip!'>Hover over me!</span></p>







            share








            New contributor




            Mike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.




















              Your Answer





              StackExchange.ifUsing("editor", function () {
              return StackExchange.using("mathjaxEditing", function () {
              StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
              StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
              });
              });
              }, "mathjax-editing");

              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "196"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: false,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f139327%2ftooltip-overlay-following-the-mouse-pointer%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              2















              Should I try to concentrate more on JavaScript only? I mean: Should I try to reduce the mandatory HTML-, CSS-code to a minimun?




              I think, the code i.e. HTML and CSS are minimal. Storing the tooltip on the HTML elements is correct way rather than storing it in JavaScript. So, NO. You should not only concentrate on JavaScript.




              Or is Okay the way I have done it?




              Yes, the logic is correct. However, the code can be shortened(see below) when written in ES6.




              But actually the first parameter (CSS-selector) is mandatory for the function to work. If it isn't correct to code will silently fail.



              Should I change that?



              Return with an exit-code which signals an error? Perhaps even throw an exception?




              Let's look at the following statement



              selector = selector || '.tooltip';


              This means, if selector is falsy, selector will be .tooltip. So, there will be no case when the selector will be empty and error will be thrown. That means, there is no need to handle that error.



              And, I'll also suggest to use [data-message] as default parameter. This will select all the elements having data-message attribute.





              Here are some suggestions:



              As let is used either the environment you're using supports ES6 or the source files are compiled to ES5.



              Following features of ES6 can be used





              1. Default Parameters



                This will allow to use the assigned value to the parameter as default value if no value is passed when invoking the function.



                Now, ES5's default parameter notation



                selector = selector || '.tooltip';


                is no longer needed.




              2. Array.from()



                Array.from() can be used to create an array from array-like structures. To iterate over the DOM elements selected by querySelectorAll(), Array.from() can be used.



                items = document.querySelectorAll(selector);
                items = Array.prototype.slice.call(items);

                items.forEach(function(item) {


                can be written as



                Array.from(document.querySelectorAll(selector))
                .forEach(function (item) {



              Updated Code:






              (function (selector = '[data-message]', horizontalOffset = 5, verticalOffset = 5) {
              'use strict';

              Array.from(document.querySelectorAll(selector)).forEach(function (item) {
              // Every time the pointer moves over the element the
              // CSS-rule in overwritten with new values for
              // top and left.
              item.addEventListener('mousemove', function (e) {
              let countCssRules = document.styleSheets[0].cssRules.length;
              let newRule = selector +
              ':hover:after { display: block; ' +
              'left: ' + (e.offsetX + horizontalOffset) + 'px; ' +
              'top: ' + (e.offsetY + verticalOffset) + 'px; }';

              document.styleSheets[0].insertRule(newRule, countCssRules);
              });
              });
              }('.tooltip-item', 10));

              .wrap {
              width: 1000px;
              margin: 50px auto;
              font-family: georgia, serif;
              background-color: cornsilk;
              padding: 20px 30px;
              }

              div.tooltip-item {
              background-color: orange;
              width: 450px;
              height: 100px;
              border: 1px solid black;
              border-radius: 8px;
              margin: 60px 10px;
              }

              .tooltip-item {
              position: relative;
              cursor: pointer;
              }

              .tooltip-item:after {
              content: attr(data-message);
              position: absolute;
              left: 105%;
              white-space: nowrap;
              display: none;
              font-size: 1.2rem;
              background-color: rgba(230, 230, 230, 0.6);
              padding: 10px 20px;
              border-radius: 16px;
              font-family: Tahoma, Verdana, Segoe, sans-serif;
              font-weight: normal;
              }

              div.tooltip-item:after {
              text-transform: uppercase;
              }

              h1.tooltip-item:after {
              background-color: cyan;
              color: #ff14ec;
              font-weight: 800;
              border-radius: 20px;
              box-shadow: 6px 6px 9px #969696;
              }

              p.tooltip-item:after {
              background-color: #232323;
              color: #efefef;
              font-weight: 800;
              border-radius: 6px;
              box-shadow: 0 0 0 grey;
              }

              <div class="wrap">
              <h1 class="tooltip-item" data-message="You are hovering the h1-element.">Demo Page - Tooltip following the Mouse-Pointer</h1>
              <div class="tooltip-item" data-message="Lorem ipsum dolor sit amet, consectetuer adipiscing elit."></div>
              <p class="tooltip-item" data-message="Paragraph-element with a tooltip attached to it.">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.</p>
              </div>








              share|improve this answer




























                2















                Should I try to concentrate more on JavaScript only? I mean: Should I try to reduce the mandatory HTML-, CSS-code to a minimun?




                I think, the code i.e. HTML and CSS are minimal. Storing the tooltip on the HTML elements is correct way rather than storing it in JavaScript. So, NO. You should not only concentrate on JavaScript.




                Or is Okay the way I have done it?




                Yes, the logic is correct. However, the code can be shortened(see below) when written in ES6.




                But actually the first parameter (CSS-selector) is mandatory for the function to work. If it isn't correct to code will silently fail.



                Should I change that?



                Return with an exit-code which signals an error? Perhaps even throw an exception?




                Let's look at the following statement



                selector = selector || '.tooltip';


                This means, if selector is falsy, selector will be .tooltip. So, there will be no case when the selector will be empty and error will be thrown. That means, there is no need to handle that error.



                And, I'll also suggest to use [data-message] as default parameter. This will select all the elements having data-message attribute.





                Here are some suggestions:



                As let is used either the environment you're using supports ES6 or the source files are compiled to ES5.



                Following features of ES6 can be used





                1. Default Parameters



                  This will allow to use the assigned value to the parameter as default value if no value is passed when invoking the function.



                  Now, ES5's default parameter notation



                  selector = selector || '.tooltip';


                  is no longer needed.




                2. Array.from()



                  Array.from() can be used to create an array from array-like structures. To iterate over the DOM elements selected by querySelectorAll(), Array.from() can be used.



                  items = document.querySelectorAll(selector);
                  items = Array.prototype.slice.call(items);

                  items.forEach(function(item) {


                  can be written as



                  Array.from(document.querySelectorAll(selector))
                  .forEach(function (item) {



                Updated Code:






                (function (selector = '[data-message]', horizontalOffset = 5, verticalOffset = 5) {
                'use strict';

                Array.from(document.querySelectorAll(selector)).forEach(function (item) {
                // Every time the pointer moves over the element the
                // CSS-rule in overwritten with new values for
                // top and left.
                item.addEventListener('mousemove', function (e) {
                let countCssRules = document.styleSheets[0].cssRules.length;
                let newRule = selector +
                ':hover:after { display: block; ' +
                'left: ' + (e.offsetX + horizontalOffset) + 'px; ' +
                'top: ' + (e.offsetY + verticalOffset) + 'px; }';

                document.styleSheets[0].insertRule(newRule, countCssRules);
                });
                });
                }('.tooltip-item', 10));

                .wrap {
                width: 1000px;
                margin: 50px auto;
                font-family: georgia, serif;
                background-color: cornsilk;
                padding: 20px 30px;
                }

                div.tooltip-item {
                background-color: orange;
                width: 450px;
                height: 100px;
                border: 1px solid black;
                border-radius: 8px;
                margin: 60px 10px;
                }

                .tooltip-item {
                position: relative;
                cursor: pointer;
                }

                .tooltip-item:after {
                content: attr(data-message);
                position: absolute;
                left: 105%;
                white-space: nowrap;
                display: none;
                font-size: 1.2rem;
                background-color: rgba(230, 230, 230, 0.6);
                padding: 10px 20px;
                border-radius: 16px;
                font-family: Tahoma, Verdana, Segoe, sans-serif;
                font-weight: normal;
                }

                div.tooltip-item:after {
                text-transform: uppercase;
                }

                h1.tooltip-item:after {
                background-color: cyan;
                color: #ff14ec;
                font-weight: 800;
                border-radius: 20px;
                box-shadow: 6px 6px 9px #969696;
                }

                p.tooltip-item:after {
                background-color: #232323;
                color: #efefef;
                font-weight: 800;
                border-radius: 6px;
                box-shadow: 0 0 0 grey;
                }

                <div class="wrap">
                <h1 class="tooltip-item" data-message="You are hovering the h1-element.">Demo Page - Tooltip following the Mouse-Pointer</h1>
                <div class="tooltip-item" data-message="Lorem ipsum dolor sit amet, consectetuer adipiscing elit."></div>
                <p class="tooltip-item" data-message="Paragraph-element with a tooltip attached to it.">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.</p>
                </div>








                share|improve this answer


























                  2












                  2








                  2








                  Should I try to concentrate more on JavaScript only? I mean: Should I try to reduce the mandatory HTML-, CSS-code to a minimun?




                  I think, the code i.e. HTML and CSS are minimal. Storing the tooltip on the HTML elements is correct way rather than storing it in JavaScript. So, NO. You should not only concentrate on JavaScript.




                  Or is Okay the way I have done it?




                  Yes, the logic is correct. However, the code can be shortened(see below) when written in ES6.




                  But actually the first parameter (CSS-selector) is mandatory for the function to work. If it isn't correct to code will silently fail.



                  Should I change that?



                  Return with an exit-code which signals an error? Perhaps even throw an exception?




                  Let's look at the following statement



                  selector = selector || '.tooltip';


                  This means, if selector is falsy, selector will be .tooltip. So, there will be no case when the selector will be empty and error will be thrown. That means, there is no need to handle that error.



                  And, I'll also suggest to use [data-message] as default parameter. This will select all the elements having data-message attribute.





                  Here are some suggestions:



                  As let is used either the environment you're using supports ES6 or the source files are compiled to ES5.



                  Following features of ES6 can be used





                  1. Default Parameters



                    This will allow to use the assigned value to the parameter as default value if no value is passed when invoking the function.



                    Now, ES5's default parameter notation



                    selector = selector || '.tooltip';


                    is no longer needed.




                  2. Array.from()



                    Array.from() can be used to create an array from array-like structures. To iterate over the DOM elements selected by querySelectorAll(), Array.from() can be used.



                    items = document.querySelectorAll(selector);
                    items = Array.prototype.slice.call(items);

                    items.forEach(function(item) {


                    can be written as



                    Array.from(document.querySelectorAll(selector))
                    .forEach(function (item) {



                  Updated Code:






                  (function (selector = '[data-message]', horizontalOffset = 5, verticalOffset = 5) {
                  'use strict';

                  Array.from(document.querySelectorAll(selector)).forEach(function (item) {
                  // Every time the pointer moves over the element the
                  // CSS-rule in overwritten with new values for
                  // top and left.
                  item.addEventListener('mousemove', function (e) {
                  let countCssRules = document.styleSheets[0].cssRules.length;
                  let newRule = selector +
                  ':hover:after { display: block; ' +
                  'left: ' + (e.offsetX + horizontalOffset) + 'px; ' +
                  'top: ' + (e.offsetY + verticalOffset) + 'px; }';

                  document.styleSheets[0].insertRule(newRule, countCssRules);
                  });
                  });
                  }('.tooltip-item', 10));

                  .wrap {
                  width: 1000px;
                  margin: 50px auto;
                  font-family: georgia, serif;
                  background-color: cornsilk;
                  padding: 20px 30px;
                  }

                  div.tooltip-item {
                  background-color: orange;
                  width: 450px;
                  height: 100px;
                  border: 1px solid black;
                  border-radius: 8px;
                  margin: 60px 10px;
                  }

                  .tooltip-item {
                  position: relative;
                  cursor: pointer;
                  }

                  .tooltip-item:after {
                  content: attr(data-message);
                  position: absolute;
                  left: 105%;
                  white-space: nowrap;
                  display: none;
                  font-size: 1.2rem;
                  background-color: rgba(230, 230, 230, 0.6);
                  padding: 10px 20px;
                  border-radius: 16px;
                  font-family: Tahoma, Verdana, Segoe, sans-serif;
                  font-weight: normal;
                  }

                  div.tooltip-item:after {
                  text-transform: uppercase;
                  }

                  h1.tooltip-item:after {
                  background-color: cyan;
                  color: #ff14ec;
                  font-weight: 800;
                  border-radius: 20px;
                  box-shadow: 6px 6px 9px #969696;
                  }

                  p.tooltip-item:after {
                  background-color: #232323;
                  color: #efefef;
                  font-weight: 800;
                  border-radius: 6px;
                  box-shadow: 0 0 0 grey;
                  }

                  <div class="wrap">
                  <h1 class="tooltip-item" data-message="You are hovering the h1-element.">Demo Page - Tooltip following the Mouse-Pointer</h1>
                  <div class="tooltip-item" data-message="Lorem ipsum dolor sit amet, consectetuer adipiscing elit."></div>
                  <p class="tooltip-item" data-message="Paragraph-element with a tooltip attached to it.">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.</p>
                  </div>








                  share|improve this answer














                  Should I try to concentrate more on JavaScript only? I mean: Should I try to reduce the mandatory HTML-, CSS-code to a minimun?




                  I think, the code i.e. HTML and CSS are minimal. Storing the tooltip on the HTML elements is correct way rather than storing it in JavaScript. So, NO. You should not only concentrate on JavaScript.




                  Or is Okay the way I have done it?




                  Yes, the logic is correct. However, the code can be shortened(see below) when written in ES6.




                  But actually the first parameter (CSS-selector) is mandatory for the function to work. If it isn't correct to code will silently fail.



                  Should I change that?



                  Return with an exit-code which signals an error? Perhaps even throw an exception?




                  Let's look at the following statement



                  selector = selector || '.tooltip';


                  This means, if selector is falsy, selector will be .tooltip. So, there will be no case when the selector will be empty and error will be thrown. That means, there is no need to handle that error.



                  And, I'll also suggest to use [data-message] as default parameter. This will select all the elements having data-message attribute.





                  Here are some suggestions:



                  As let is used either the environment you're using supports ES6 or the source files are compiled to ES5.



                  Following features of ES6 can be used





                  1. Default Parameters



                    This will allow to use the assigned value to the parameter as default value if no value is passed when invoking the function.



                    Now, ES5's default parameter notation



                    selector = selector || '.tooltip';


                    is no longer needed.




                  2. Array.from()



                    Array.from() can be used to create an array from array-like structures. To iterate over the DOM elements selected by querySelectorAll(), Array.from() can be used.



                    items = document.querySelectorAll(selector);
                    items = Array.prototype.slice.call(items);

                    items.forEach(function(item) {


                    can be written as



                    Array.from(document.querySelectorAll(selector))
                    .forEach(function (item) {



                  Updated Code:






                  (function (selector = '[data-message]', horizontalOffset = 5, verticalOffset = 5) {
                  'use strict';

                  Array.from(document.querySelectorAll(selector)).forEach(function (item) {
                  // Every time the pointer moves over the element the
                  // CSS-rule in overwritten with new values for
                  // top and left.
                  item.addEventListener('mousemove', function (e) {
                  let countCssRules = document.styleSheets[0].cssRules.length;
                  let newRule = selector +
                  ':hover:after { display: block; ' +
                  'left: ' + (e.offsetX + horizontalOffset) + 'px; ' +
                  'top: ' + (e.offsetY + verticalOffset) + 'px; }';

                  document.styleSheets[0].insertRule(newRule, countCssRules);
                  });
                  });
                  }('.tooltip-item', 10));

                  .wrap {
                  width: 1000px;
                  margin: 50px auto;
                  font-family: georgia, serif;
                  background-color: cornsilk;
                  padding: 20px 30px;
                  }

                  div.tooltip-item {
                  background-color: orange;
                  width: 450px;
                  height: 100px;
                  border: 1px solid black;
                  border-radius: 8px;
                  margin: 60px 10px;
                  }

                  .tooltip-item {
                  position: relative;
                  cursor: pointer;
                  }

                  .tooltip-item:after {
                  content: attr(data-message);
                  position: absolute;
                  left: 105%;
                  white-space: nowrap;
                  display: none;
                  font-size: 1.2rem;
                  background-color: rgba(230, 230, 230, 0.6);
                  padding: 10px 20px;
                  border-radius: 16px;
                  font-family: Tahoma, Verdana, Segoe, sans-serif;
                  font-weight: normal;
                  }

                  div.tooltip-item:after {
                  text-transform: uppercase;
                  }

                  h1.tooltip-item:after {
                  background-color: cyan;
                  color: #ff14ec;
                  font-weight: 800;
                  border-radius: 20px;
                  box-shadow: 6px 6px 9px #969696;
                  }

                  p.tooltip-item:after {
                  background-color: #232323;
                  color: #efefef;
                  font-weight: 800;
                  border-radius: 6px;
                  box-shadow: 0 0 0 grey;
                  }

                  <div class="wrap">
                  <h1 class="tooltip-item" data-message="You are hovering the h1-element.">Demo Page - Tooltip following the Mouse-Pointer</h1>
                  <div class="tooltip-item" data-message="Lorem ipsum dolor sit amet, consectetuer adipiscing elit."></div>
                  <p class="tooltip-item" data-message="Paragraph-element with a tooltip attached to it.">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.</p>
                  </div>








                  (function (selector = '[data-message]', horizontalOffset = 5, verticalOffset = 5) {
                  'use strict';

                  Array.from(document.querySelectorAll(selector)).forEach(function (item) {
                  // Every time the pointer moves over the element the
                  // CSS-rule in overwritten with new values for
                  // top and left.
                  item.addEventListener('mousemove', function (e) {
                  let countCssRules = document.styleSheets[0].cssRules.length;
                  let newRule = selector +
                  ':hover:after { display: block; ' +
                  'left: ' + (e.offsetX + horizontalOffset) + 'px; ' +
                  'top: ' + (e.offsetY + verticalOffset) + 'px; }';

                  document.styleSheets[0].insertRule(newRule, countCssRules);
                  });
                  });
                  }('.tooltip-item', 10));

                  .wrap {
                  width: 1000px;
                  margin: 50px auto;
                  font-family: georgia, serif;
                  background-color: cornsilk;
                  padding: 20px 30px;
                  }

                  div.tooltip-item {
                  background-color: orange;
                  width: 450px;
                  height: 100px;
                  border: 1px solid black;
                  border-radius: 8px;
                  margin: 60px 10px;
                  }

                  .tooltip-item {
                  position: relative;
                  cursor: pointer;
                  }

                  .tooltip-item:after {
                  content: attr(data-message);
                  position: absolute;
                  left: 105%;
                  white-space: nowrap;
                  display: none;
                  font-size: 1.2rem;
                  background-color: rgba(230, 230, 230, 0.6);
                  padding: 10px 20px;
                  border-radius: 16px;
                  font-family: Tahoma, Verdana, Segoe, sans-serif;
                  font-weight: normal;
                  }

                  div.tooltip-item:after {
                  text-transform: uppercase;
                  }

                  h1.tooltip-item:after {
                  background-color: cyan;
                  color: #ff14ec;
                  font-weight: 800;
                  border-radius: 20px;
                  box-shadow: 6px 6px 9px #969696;
                  }

                  p.tooltip-item:after {
                  background-color: #232323;
                  color: #efefef;
                  font-weight: 800;
                  border-radius: 6px;
                  box-shadow: 0 0 0 grey;
                  }

                  <div class="wrap">
                  <h1 class="tooltip-item" data-message="You are hovering the h1-element.">Demo Page - Tooltip following the Mouse-Pointer</h1>
                  <div class="tooltip-item" data-message="Lorem ipsum dolor sit amet, consectetuer adipiscing elit."></div>
                  <p class="tooltip-item" data-message="Paragraph-element with a tooltip attached to it.">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.</p>
                  </div>





                  (function (selector = '[data-message]', horizontalOffset = 5, verticalOffset = 5) {
                  'use strict';

                  Array.from(document.querySelectorAll(selector)).forEach(function (item) {
                  // Every time the pointer moves over the element the
                  // CSS-rule in overwritten with new values for
                  // top and left.
                  item.addEventListener('mousemove', function (e) {
                  let countCssRules = document.styleSheets[0].cssRules.length;
                  let newRule = selector +
                  ':hover:after { display: block; ' +
                  'left: ' + (e.offsetX + horizontalOffset) + 'px; ' +
                  'top: ' + (e.offsetY + verticalOffset) + 'px; }';

                  document.styleSheets[0].insertRule(newRule, countCssRules);
                  });
                  });
                  }('.tooltip-item', 10));

                  .wrap {
                  width: 1000px;
                  margin: 50px auto;
                  font-family: georgia, serif;
                  background-color: cornsilk;
                  padding: 20px 30px;
                  }

                  div.tooltip-item {
                  background-color: orange;
                  width: 450px;
                  height: 100px;
                  border: 1px solid black;
                  border-radius: 8px;
                  margin: 60px 10px;
                  }

                  .tooltip-item {
                  position: relative;
                  cursor: pointer;
                  }

                  .tooltip-item:after {
                  content: attr(data-message);
                  position: absolute;
                  left: 105%;
                  white-space: nowrap;
                  display: none;
                  font-size: 1.2rem;
                  background-color: rgba(230, 230, 230, 0.6);
                  padding: 10px 20px;
                  border-radius: 16px;
                  font-family: Tahoma, Verdana, Segoe, sans-serif;
                  font-weight: normal;
                  }

                  div.tooltip-item:after {
                  text-transform: uppercase;
                  }

                  h1.tooltip-item:after {
                  background-color: cyan;
                  color: #ff14ec;
                  font-weight: 800;
                  border-radius: 20px;
                  box-shadow: 6px 6px 9px #969696;
                  }

                  p.tooltip-item:after {
                  background-color: #232323;
                  color: #efefef;
                  font-weight: 800;
                  border-radius: 6px;
                  box-shadow: 0 0 0 grey;
                  }

                  <div class="wrap">
                  <h1 class="tooltip-item" data-message="You are hovering the h1-element.">Demo Page - Tooltip following the Mouse-Pointer</h1>
                  <div class="tooltip-item" data-message="Lorem ipsum dolor sit amet, consectetuer adipiscing elit."></div>
                  <p class="tooltip-item" data-message="Paragraph-element with a tooltip attached to it.">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.</p>
                  </div>






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Aug 22 '16 at 7:38









                  TusharTushar

                  2,77011425




                  2,77011425

























                      0














                      I found this post and took your code and made some changes. I wanted to have a very small piece of javascript code that supported style-able tooltips.



                      First, the way you were editing the CSS was to add an additional style every time the mouse moves. This will create hundreds of style additions in just a few seconds of mouse movement, so very inefficient over time. To avoid this, I created a blank style for the hover class and preserved reference to this style definition. I then modified the style using this reference, rather than creating new styles every time the handler is called.



                      Second, the code doesn't account for if the value is blank. The tooltip will show a blank box, instead of not showing at all. So I added a conditional to hide the tooltip if this is case.



                      Third, you can select a CSS style by data attribute, so there is no need to specify a .tooltip class for the element. So I dropped that.



                      Forth, setting the position of the tooltip element relative to the hover element has glitches. If the hover element is inside another element, the tooltip width will be glitchy and often too narrow if the parent element is something small, like a table cell. There are workarounds, such as setting a fixed width of the tooltip element, but this isn't ideal. There is another workaround to contain the tooltip in a wrapper div, but you cannot do this because html is not allowed when using the CSS content attribute. The fix I used is to set the tooltip to "display: fixed", and set position based on screen coordinates. This allows me to use max-width while shorter tooltips are only the width of the text.



                      A final note: this solution is probably not ideal on a mobile device. But I am using this for a desktop environment, so it works for this class of usage.






                      document.addEventListener('DOMContentLoaded', function() {
                      var cssSheet = document.styleSheets[0];
                      var hoverIndex = cssSheet.insertRule('[data-tooltip]:hover:after {}', cssSheet.cssRules.length);
                      var cssHover = cssSheet.cssRules[hoverIndex];
                      Array.from(document.querySelectorAll('[data-tooltip]')).forEach(function (item) {
                      item.addEventListener('mousemove', function (e) {
                      if (this.dataset.tooltip == '') {
                      cssHover.style.display = 'none';
                      return;
                      }
                      cssHover.style.display = 'block';
                      cssHover.style.left = (e.clientX + 15) + 'px';
                      cssHover.style.top = (e.clientY + 15) + 'px';
                      });
                      });
                      });

                      [data-tooltip] {
                      border-bottom: 1px dotted #777;
                      cursor: help;
                      }

                      [data-tooltip]:after {
                      content: attr(data-tooltip);
                      display: none;
                      position: fixed;
                      max-width: 600px;
                      background: #ffd;
                      border: 1px solid #999;
                      padding: 12px;
                      color: #000;
                      border-radius: 3px;
                      margin: 0;
                      font-size: 14px;

                      left: 50px;
                      top:25px;
                      z-index: 10;

                      box-shadow: 0px 0px 5px rgba(0,0,0,.2);

                      line-height: 1.3em;
                      }

                      <p><span data-tooltip='I am a tooltip!'>Hover over me!</span></p>







                      share








                      New contributor




                      Mike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                      Check out our Code of Conduct.

























                        0














                        I found this post and took your code and made some changes. I wanted to have a very small piece of javascript code that supported style-able tooltips.



                        First, the way you were editing the CSS was to add an additional style every time the mouse moves. This will create hundreds of style additions in just a few seconds of mouse movement, so very inefficient over time. To avoid this, I created a blank style for the hover class and preserved reference to this style definition. I then modified the style using this reference, rather than creating new styles every time the handler is called.



                        Second, the code doesn't account for if the value is blank. The tooltip will show a blank box, instead of not showing at all. So I added a conditional to hide the tooltip if this is case.



                        Third, you can select a CSS style by data attribute, so there is no need to specify a .tooltip class for the element. So I dropped that.



                        Forth, setting the position of the tooltip element relative to the hover element has glitches. If the hover element is inside another element, the tooltip width will be glitchy and often too narrow if the parent element is something small, like a table cell. There are workarounds, such as setting a fixed width of the tooltip element, but this isn't ideal. There is another workaround to contain the tooltip in a wrapper div, but you cannot do this because html is not allowed when using the CSS content attribute. The fix I used is to set the tooltip to "display: fixed", and set position based on screen coordinates. This allows me to use max-width while shorter tooltips are only the width of the text.



                        A final note: this solution is probably not ideal on a mobile device. But I am using this for a desktop environment, so it works for this class of usage.






                        document.addEventListener('DOMContentLoaded', function() {
                        var cssSheet = document.styleSheets[0];
                        var hoverIndex = cssSheet.insertRule('[data-tooltip]:hover:after {}', cssSheet.cssRules.length);
                        var cssHover = cssSheet.cssRules[hoverIndex];
                        Array.from(document.querySelectorAll('[data-tooltip]')).forEach(function (item) {
                        item.addEventListener('mousemove', function (e) {
                        if (this.dataset.tooltip == '') {
                        cssHover.style.display = 'none';
                        return;
                        }
                        cssHover.style.display = 'block';
                        cssHover.style.left = (e.clientX + 15) + 'px';
                        cssHover.style.top = (e.clientY + 15) + 'px';
                        });
                        });
                        });

                        [data-tooltip] {
                        border-bottom: 1px dotted #777;
                        cursor: help;
                        }

                        [data-tooltip]:after {
                        content: attr(data-tooltip);
                        display: none;
                        position: fixed;
                        max-width: 600px;
                        background: #ffd;
                        border: 1px solid #999;
                        padding: 12px;
                        color: #000;
                        border-radius: 3px;
                        margin: 0;
                        font-size: 14px;

                        left: 50px;
                        top:25px;
                        z-index: 10;

                        box-shadow: 0px 0px 5px rgba(0,0,0,.2);

                        line-height: 1.3em;
                        }

                        <p><span data-tooltip='I am a tooltip!'>Hover over me!</span></p>







                        share








                        New contributor




                        Mike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                        Check out our Code of Conduct.























                          0












                          0








                          0







                          I found this post and took your code and made some changes. I wanted to have a very small piece of javascript code that supported style-able tooltips.



                          First, the way you were editing the CSS was to add an additional style every time the mouse moves. This will create hundreds of style additions in just a few seconds of mouse movement, so very inefficient over time. To avoid this, I created a blank style for the hover class and preserved reference to this style definition. I then modified the style using this reference, rather than creating new styles every time the handler is called.



                          Second, the code doesn't account for if the value is blank. The tooltip will show a blank box, instead of not showing at all. So I added a conditional to hide the tooltip if this is case.



                          Third, you can select a CSS style by data attribute, so there is no need to specify a .tooltip class for the element. So I dropped that.



                          Forth, setting the position of the tooltip element relative to the hover element has glitches. If the hover element is inside another element, the tooltip width will be glitchy and often too narrow if the parent element is something small, like a table cell. There are workarounds, such as setting a fixed width of the tooltip element, but this isn't ideal. There is another workaround to contain the tooltip in a wrapper div, but you cannot do this because html is not allowed when using the CSS content attribute. The fix I used is to set the tooltip to "display: fixed", and set position based on screen coordinates. This allows me to use max-width while shorter tooltips are only the width of the text.



                          A final note: this solution is probably not ideal on a mobile device. But I am using this for a desktop environment, so it works for this class of usage.






                          document.addEventListener('DOMContentLoaded', function() {
                          var cssSheet = document.styleSheets[0];
                          var hoverIndex = cssSheet.insertRule('[data-tooltip]:hover:after {}', cssSheet.cssRules.length);
                          var cssHover = cssSheet.cssRules[hoverIndex];
                          Array.from(document.querySelectorAll('[data-tooltip]')).forEach(function (item) {
                          item.addEventListener('mousemove', function (e) {
                          if (this.dataset.tooltip == '') {
                          cssHover.style.display = 'none';
                          return;
                          }
                          cssHover.style.display = 'block';
                          cssHover.style.left = (e.clientX + 15) + 'px';
                          cssHover.style.top = (e.clientY + 15) + 'px';
                          });
                          });
                          });

                          [data-tooltip] {
                          border-bottom: 1px dotted #777;
                          cursor: help;
                          }

                          [data-tooltip]:after {
                          content: attr(data-tooltip);
                          display: none;
                          position: fixed;
                          max-width: 600px;
                          background: #ffd;
                          border: 1px solid #999;
                          padding: 12px;
                          color: #000;
                          border-radius: 3px;
                          margin: 0;
                          font-size: 14px;

                          left: 50px;
                          top:25px;
                          z-index: 10;

                          box-shadow: 0px 0px 5px rgba(0,0,0,.2);

                          line-height: 1.3em;
                          }

                          <p><span data-tooltip='I am a tooltip!'>Hover over me!</span></p>







                          share








                          New contributor




                          Mike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                          Check out our Code of Conduct.










                          I found this post and took your code and made some changes. I wanted to have a very small piece of javascript code that supported style-able tooltips.



                          First, the way you were editing the CSS was to add an additional style every time the mouse moves. This will create hundreds of style additions in just a few seconds of mouse movement, so very inefficient over time. To avoid this, I created a blank style for the hover class and preserved reference to this style definition. I then modified the style using this reference, rather than creating new styles every time the handler is called.



                          Second, the code doesn't account for if the value is blank. The tooltip will show a blank box, instead of not showing at all. So I added a conditional to hide the tooltip if this is case.



                          Third, you can select a CSS style by data attribute, so there is no need to specify a .tooltip class for the element. So I dropped that.



                          Forth, setting the position of the tooltip element relative to the hover element has glitches. If the hover element is inside another element, the tooltip width will be glitchy and often too narrow if the parent element is something small, like a table cell. There are workarounds, such as setting a fixed width of the tooltip element, but this isn't ideal. There is another workaround to contain the tooltip in a wrapper div, but you cannot do this because html is not allowed when using the CSS content attribute. The fix I used is to set the tooltip to "display: fixed", and set position based on screen coordinates. This allows me to use max-width while shorter tooltips are only the width of the text.



                          A final note: this solution is probably not ideal on a mobile device. But I am using this for a desktop environment, so it works for this class of usage.






                          document.addEventListener('DOMContentLoaded', function() {
                          var cssSheet = document.styleSheets[0];
                          var hoverIndex = cssSheet.insertRule('[data-tooltip]:hover:after {}', cssSheet.cssRules.length);
                          var cssHover = cssSheet.cssRules[hoverIndex];
                          Array.from(document.querySelectorAll('[data-tooltip]')).forEach(function (item) {
                          item.addEventListener('mousemove', function (e) {
                          if (this.dataset.tooltip == '') {
                          cssHover.style.display = 'none';
                          return;
                          }
                          cssHover.style.display = 'block';
                          cssHover.style.left = (e.clientX + 15) + 'px';
                          cssHover.style.top = (e.clientY + 15) + 'px';
                          });
                          });
                          });

                          [data-tooltip] {
                          border-bottom: 1px dotted #777;
                          cursor: help;
                          }

                          [data-tooltip]:after {
                          content: attr(data-tooltip);
                          display: none;
                          position: fixed;
                          max-width: 600px;
                          background: #ffd;
                          border: 1px solid #999;
                          padding: 12px;
                          color: #000;
                          border-radius: 3px;
                          margin: 0;
                          font-size: 14px;

                          left: 50px;
                          top:25px;
                          z-index: 10;

                          box-shadow: 0px 0px 5px rgba(0,0,0,.2);

                          line-height: 1.3em;
                          }

                          <p><span data-tooltip='I am a tooltip!'>Hover over me!</span></p>








                          document.addEventListener('DOMContentLoaded', function() {
                          var cssSheet = document.styleSheets[0];
                          var hoverIndex = cssSheet.insertRule('[data-tooltip]:hover:after {}', cssSheet.cssRules.length);
                          var cssHover = cssSheet.cssRules[hoverIndex];
                          Array.from(document.querySelectorAll('[data-tooltip]')).forEach(function (item) {
                          item.addEventListener('mousemove', function (e) {
                          if (this.dataset.tooltip == '') {
                          cssHover.style.display = 'none';
                          return;
                          }
                          cssHover.style.display = 'block';
                          cssHover.style.left = (e.clientX + 15) + 'px';
                          cssHover.style.top = (e.clientY + 15) + 'px';
                          });
                          });
                          });

                          [data-tooltip] {
                          border-bottom: 1px dotted #777;
                          cursor: help;
                          }

                          [data-tooltip]:after {
                          content: attr(data-tooltip);
                          display: none;
                          position: fixed;
                          max-width: 600px;
                          background: #ffd;
                          border: 1px solid #999;
                          padding: 12px;
                          color: #000;
                          border-radius: 3px;
                          margin: 0;
                          font-size: 14px;

                          left: 50px;
                          top:25px;
                          z-index: 10;

                          box-shadow: 0px 0px 5px rgba(0,0,0,.2);

                          line-height: 1.3em;
                          }

                          <p><span data-tooltip='I am a tooltip!'>Hover over me!</span></p>





                          document.addEventListener('DOMContentLoaded', function() {
                          var cssSheet = document.styleSheets[0];
                          var hoverIndex = cssSheet.insertRule('[data-tooltip]:hover:after {}', cssSheet.cssRules.length);
                          var cssHover = cssSheet.cssRules[hoverIndex];
                          Array.from(document.querySelectorAll('[data-tooltip]')).forEach(function (item) {
                          item.addEventListener('mousemove', function (e) {
                          if (this.dataset.tooltip == '') {
                          cssHover.style.display = 'none';
                          return;
                          }
                          cssHover.style.display = 'block';
                          cssHover.style.left = (e.clientX + 15) + 'px';
                          cssHover.style.top = (e.clientY + 15) + 'px';
                          });
                          });
                          });

                          [data-tooltip] {
                          border-bottom: 1px dotted #777;
                          cursor: help;
                          }

                          [data-tooltip]:after {
                          content: attr(data-tooltip);
                          display: none;
                          position: fixed;
                          max-width: 600px;
                          background: #ffd;
                          border: 1px solid #999;
                          padding: 12px;
                          color: #000;
                          border-radius: 3px;
                          margin: 0;
                          font-size: 14px;

                          left: 50px;
                          top:25px;
                          z-index: 10;

                          box-shadow: 0px 0px 5px rgba(0,0,0,.2);

                          line-height: 1.3em;
                          }

                          <p><span data-tooltip='I am a tooltip!'>Hover over me!</span></p>





                          share








                          New contributor




                          Mike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                          Check out our Code of Conduct.








                          share


                          share






                          New contributor




                          Mike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                          Check out our Code of Conduct.









                          answered 5 mins ago









                          MikeMike

                          1




                          1




                          New contributor




                          Mike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                          Check out our Code of Conduct.





                          New contributor





                          Mike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                          Check out our Code of Conduct.






                          Mike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                          Check out our Code of Conduct.






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Code Review Stack Exchange!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              Use MathJax to format equations. MathJax reference.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f139327%2ftooltip-overlay-following-the-mouse-pointer%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              List directoties down one level, excluding some named directories and files

                              list processes belonging to a network namespace

                              list systemd RuntimeDirectory mounts