【问题标题】:Plain JavaScript tooltip纯 JavaScript 工具提示
【发布时间】:2013-08-23 22:18:12
【问题描述】:

我正在尝试用纯 JavaScript 制作工具提示,显示在 hover 上。就像 Stack Overflow 中的一样,将鼠标悬停在配置文件名称上时,会显示 div

我尝试使用 onmouseoveronmouseout 并添加了 setTimeout 让用户有几秒钟的时间将鼠标移到工具提示内容上。但它并没有像我想象的那样工作。

比起使用任何库,我真的更喜欢纯 JavaScript。有人能帮帮我吗?


这是我在纯 JavaScript 中所做的。

HTML

<div class = "name" onmouseover="show()" onmouseout="hide()">
    NAME
        <div class = "tooltip">
            PROFILE DETAILS
        </div>
    </div>

    <div class = "name" onmouseover="show()" onmouseout="hide()">
    NAME 2
        <div class = "tooltip" >
            PROFILE DETAILS 2
        </div>
    </div>

    <div class = "name" onmouseover="show()" onmouseout="hide()">
    NAME 3
        <div class = "tooltip" >
            PROFILE DETAILS 3
        </div>
    </div>

CSS

.name{
        float:left;
        margin:100px;
        border:1px solid black;
    }
    .tooltip{
        position:absolute;
        margin:5px;
        width:200px;
        height:100px;
        border:1px solid black;
        display:none;
    }

JavaScript

var name = document.getElementsByclassName("name");
    var tp = document.getElementsByclassName("tooltip");

    function show(){
        tp.style.display="block";
    }
    function hide(){
        tp.style.display="";
    }

【问题讨论】:

  • 为什么要使用 JavaScript?纯 CSS 可以工作...
  • 查看此链接jqueryui.com/tooltip
  • 在纯 js 中我需要使用过渡来使内容停留几秒钟,这对跨浏览器没有帮助
  • 我不想要 jQuery 我需要纯 javascript
  • 我做到了并在 jsfiddle 中进行了检查,但它不起作用

标签: javascript tooltip


【解决方案1】:

没有 JavaScript 的解决方案

这使用 CSS 伪悬停来设置隐藏元素的显示。显示 none 需要在样式中而不是在元素上,以便可以在悬停时覆盖。

.couponcode:hover .coupontooltip {
  /* NEW */
  display: block;
}

.coupontooltip {
  display: none;
  /* NEW */
  background: #C8C8C8;
  margin-left: 28px;
  padding: 10px;
  position: absolute;
  z-index: 1000;
  width: 200px;
  height: 100px;
}

.couponcode {
  margin: 100px;
}
<div class="couponcode">First Link
  <span class="coupontooltip">Content 1</span>
  <!-- UPDATED -->
</div>

<div class="couponcode">Second Link
  <span class="coupontooltip"> Content 2</span>
  <!-- UPDATED -->
</div>

External Link

跟进:

如果您需要支持非常旧的浏览器,则需要在鼠标进入 div 时向外部元素添加一个类。并在鼠标离开时删除该类。


编辑

您的代码不起作用,因为 tp 是什么?是元素的集合,您将其视为一个。您需要做的是传递对元素的引用

HTML:

<div class = "name" onmouseover="show(this)" onmouseout="hide(this)">  <!-- added "this" 2 times -->

**JavaScript:

//var name = document.getElementsByclassName("name");  /* not needed */
//    var tp = document.getElementsByclassName("tooltip"); /* not needed */


function show (elem) {  /* added argument */
    elem.style.display="block"; /* changed variable to argument */
}
function hide (elem) { /* added argument */
    elem.style.display="";  /* changed variable to argument */
}

【讨论】:

  • 如果我想在工具提示中使用 ajax 从数据库中获取内容,这会有所帮助
  • 这是一个优雅的解决方案,值得 IMO 获得更多投票。小提琴很棒+1
  • @MemetOlsen,我喜欢这个工具提示。有没有办法将工具提示移动到控件的右边缘?我知道它使用的是左边距,但是有没有办法让它,比如从输入框的最右边开始?
  • :hover&gt;.coupontooltip 可以让您将工具提示放在任何内容中。
【解决方案2】:

对于非自定义工具提示,您可以在主div的标题属性中添加您想要在工具提示中显示的消息。就像这样:

<div class = "name" onmouseover="show()" onmouseout="hide()" title="PROFILE DETAILS">

那么就不需要添加onmouseoveronmouseout事件处理器了。

【讨论】:

    【解决方案3】:

    修复原代码

    我一直在寻找类似的东西,我偶然发现了这个页面。 它帮助了我,但我必须修复你的代码,它才能工作。我认为这就是你所尝试的。 您必须通过对象的“ID”引用您的对象。 这是我所做的,并且有效:

    function show(elem) {
      elem.style.display = "block";
    }
    
    function hide(elem) {
      elem.style.display = "";
    }
    .name {
      float: left;
      margin: 100px;
      border: 1px solid black;
    }
    
    .tooltip {
      position: absolute;
      margin: 5px;
      width: 200px;
      height: 50px;
      border: 1px solid black;
      display: none;
    }
    <div class="name" onmouseover="show(tooltip1)" onmouseout="hide(tooltip1)">
      NAME
      <div class="tooltip" id="tooltip1">
        PROFILE DETAILS
      </div>
    </div>
    
    <div class="name" onmouseover="show(tooltip2)" onmouseout="hide(tooltip2)">
      NAME 2
      <div class="tooltip" id="tooltip2">
        PROFILE DETAILS 2
      </div>
    </div>
    
    <div class="name" onmouseover="show(tooltip3)" onmouseout="hide(tooltip3)">
      NAME 3
      <div class="tooltip" id="tooltip3">
        PROFILE DETAILS 3
      </div>
    </div>

    External link

    【讨论】:

      【解决方案4】:

      即使是 $(document).ready,在纯 JS 中也很难完成——请看这里: $(document).ready equivalent without jQuery

      所以我使用的是简单版本:

      window.addEventListener("load", function () {
          var couponcodes = document.getElementsByClassName("couponcode");
          for (var i = 0; i < couponcodes.length; i++) {
              couponcodes[i].addEventListener("mouseover", function () {
                  var coupontooltip = this.getElementsByClassName("coupontooltip")[0];
                  coupontooltip.removeAttribute("style");
              });
              couponcodes[i].addEventListener("mouseout", function () {
                  var coupontooltip = this.getElementsByClassName("coupontooltip")[0];
                  coupontooltip.style.display = "none";
              });
          }
      });
      

      http://jsfiddle.net/mynetx/5qbP3/

      【讨论】:

        【解决方案5】:

        问题说:

        纯 JavaScript 工具提示

        但我认为在现代我们可以使用 vanilla JS 和 CSS。特别是,当我们想要提供好看的样式时,这是必须的。

        这个例子是纯 JS 和 CSS 的简单实现。

        让我们使用CSS 创建一个工具提示,并使用JS 添加修改行为。在本例中,我们将定义一个tip 属性来存储将在工具提示上显示的文本。

        visibility: hidden;opacity: 0; 将保持.tooltip 隐藏,并在[tip]:hover 时出现。此外,我们可以使用style.transform 显示工具提示中的发射点。

        Array.from(document.querySelectorAll('[tip]')).forEach(el => {
          let tip = document.createElement('div');
          tip.classList.add('tooltip');
          tip.innerText = el.getAttribute('tip');
          tip.style.transform =
            'translate(' +
              (el.hasAttribute('tip-left') ? 'calc(-100% - 5px)' : '15px') + ', ' +
              (el.hasAttribute('tip-top') ? '-100%' : '0') +
            ')';
          el.appendChild(tip);
          el.onmousemove = e => {
            tip.style.left = e.clientX + 'px'
            tip.style.top = e.clientY + 'px';
          };
        });
        [tip] .tooltip {
          position: fixed;
          font-size: 16px;
          line-height: 20px;
          padding: 5px;
          background: white;
          border: 1px solid #ccc;
          visibility: hidden;
          opacity: 0;
          box-shadow: -2px 2px 5px rgba(0, 0, 0, 0.2);
          transition: opacity 0.3s, visibility 0s;
        }
        
        [tip]:hover .tooltip {
          visibility: visible;
          opacity: 1;
        }
        
        button {
          display: block;
          cursor: pointer;
          padding: 8px 15px;
          border: 1px solid gray;
          border-radius: 4px;
          margin: 50px;
          font-size: 18px;
          background: white;
        }
        
        button:hover {
          border-color: dodgerblue;
        }
        <button tip="Click Me!">
          I have a tooltip
        </button>
        <button tip="Click Me Aswell!" tip-top tip-left>
          Top-left tooltip
        </button>

        【讨论】:

          【解决方案6】:

          document.addEventListener("mousemove",function awesome(e){
          if(e.target.id != ""){
          e.target.title = "#"+e.target.id;
          }
          }); 
          <div id="dkf">random stuff</div>
          <div id="dkls">some more random stuff</div>

          你可以用很多其他的东西来做到这一点,比如 className、tagName 等等......

          【讨论】:

            【解决方案7】:

            在使用 popper+tippy 时遇到了一些滞后,开始搜索替代品并找到了 @Teocci 的 great answer above

            我需要进行以下调整,所以这是修改后的代码:

            • 由于 css/innerHTML 冲突,将提示添加到正文,而不是 el
            • 使用js mouseevents切换,防止嵌套触发器
            • 总是底部用例的箭头
            • 能够清除之前所有使用 DOM 更改进行动态调用的提示

            CSS

            .tooltip {
                position: fixed;
                z-index: 99;
                font-size: 12px;
                line-height: 12px;
                padding: 5px;
                background: #222;
                color: #fff;
                border: 1px solid #aaa;
                border-radius: 5px;
                font-family: sans-serif;
                box-sizing: border-box;
                /*box-shadow: -1px 2px 5px rgba(0, 0, 0, 0.2);*/
                transition: opacity 0.3s, visibility 0s;
                visibility: hidden;
                opacity: 0;
            }
            
            .tooltip-arrow{
                position: absolute;
                top: -4px;
                width: 7px;
                height: 7px;
                background: inherit;
                transform: rotate(45deg);
                border-top: 1px solid #aaa;
                border-left: 1px solid #aaa;
            }
            
            /* just for demo */
            .box{
                margin: 25px;
                padding: 25px;
            }
            

            HTML

            <div class="box" style="background:orange;" data-tip="hello i'm the parent">
                <div class="box" style="background:green;" data-tip="hi i'm the child"></div>
            </div>
            

            JS

            function initTips(){
                // purge previous for dynamic render
                Array.from(document.querySelectorAll('.tooltip')).forEach(el => {
                    el.remove()
                })
            
                // built upon: https://stackoverflow.com/a/69340293/10885535
                Array.from(document.querySelectorAll('[data-tip]')).forEach(el => {
                    // tip
                    let tip = document.createElement('div')
                    tip.classList.add('tooltip')
                    tip.innerText = el.getAttribute('data-tip')
                    document.body.appendChild(tip)
            
                    // arrow
                    let arrow = document.createElement('div')
                    arrow.classList.add('tooltip-arrow')
                    tip.appendChild(arrow)
            
                    // position tip + arrow once added
                    setTimeout(() => {
                        let elmPos = el.getBoundingClientRect()
                        let tipPos = tip.getBoundingClientRect()
                        tip.style.left = (elmPos.left + (elmPos.width - tipPos.width)/2) + 'px'
                        tip.style.top = (elmPos.bottom + 5)+'px'
                        arrow.style.left = (tipPos.width/2 - 5) + 'px'
                    }, 0)
            
                    // toggle with mouse
                    el.onmouseover = e => {
                        tip.style.opacity = 1
                        tip.style.visibility = 'visible'
                        e.stopPropagation() // stop parent
                    };
                     el.onmouseout = e => {
                        tip.style.opacity = 0
                        tip.style.visibility = 'hidden'
                    };
                });
            }
            
            // kickoff
            initTips()
            
            // test calling again ie after dynamic content
            setTimeout(initTips, 1000)
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-11-11
              • 1970-01-01
              • 2020-01-20
              • 1970-01-01
              相关资源
              最近更新 更多