【问题标题】:Prevent CSS tooltip from going out of page/window防止 CSS 工具提示离开页面/窗口
【发布时间】:2018-07-11 15:33:08
【问题描述】:

我有一个纯 CSS 工具提示,当您 hover 链接时,它会加载 span 作为工具提示。然而,这是使用 CSS 定位的,但如果链接靠近页面顶部或侧面,则工具提示会离开页面的侧面/顶部。

有没有办法用 css 来做这个改变,还是我必须依赖 JS? 我已经开始尝试将一些东西与 jQuery 放在一起,但如果可能的话,我宁愿使用 CSS。

https://jsfiddle.net/gtoprh21/12/ 的 JS 小提琴

片段:

$( ".ktooltip" )
.mouseover(function(e) {
   var mousex = e.pageX + 20; //Get X coordinates
   var mousey = e.pageY + 10; //Get Y coordinates
   if((mousey+100)>$(window).height())
   {

    $('.tooltip')
    .css({ top: mousey-100 ,left: mousex })

   }
   else if((mousex+200)>$(window).width())
   {
      $('.tooltip')
    .css({ top: mousey ,left: mousex-200})

   }
   else
    {
   $('.tooltip')
    .css({ top: mousey, left: mousex })

    }
})
.ref, .refs {
  position:relative;
}
/*added a text indent to overide indent styles further down*/
.ktooltip {
    display: inline-block;
    text-indent:0em;
}

.ref .ktooltiptext, .refs .ktooltiptext {
  visibility:hidden;
  width: 200px;
  background: #fff;
  border-radius: 6px;
  padding: 5px 5px;
  top: -40px;
  left: 10px;
  border:2px solid grey;
  line-height: normal;

    /* Position the tooltip */
    position: absolute;
    z-index: 1;
}

.ref:hover .ktooltiptext, .refs:hover .ktooltiptext {
    visibility: visible;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>
 <span id="edtxt.trans1" class="tei l">My hope is in a bishop,
 <!--link to a reference -->
   <sup class="ref expl">
     <a href="#edtxt-explnote1" id="reference-to-edtxt-explnote1" class="ktooltip">1</a>
       <!-- lhe reference in a tooltip -->
       <span class="ktooltiptext">According to tradition <span style="name">Nicholas</span> was bishop of Myra in Lycia (south-west Turkey today).</span>
   </sup>
  </span><br>
  <span id="trans2" class="tei l">and in almighty God and his never-ending miracles.</span><br>
  <span id="trans3" class="tei l">Generous Saint Nicholas holds an office,</span><br>
  <span id="trans4" class="tei l">there is a gold symbol in his sign.
    <!-- likn to ref -->
    <sup class="ref expl">
      <a href="#edtxt-explnote2" id="reference-to-edtxt-explnote2" class="ktooltip">2</a>
        <!-- the tooltip -->
        <span class="ktooltiptext"> One of <span style="">Nicholas’s</span> symbols was three <sup>bags</sup> of gold <span style="font-variant: small-caps;">which</span> were the <span style="color: red;">dowry</span> he provided <span style="color: blue;">for</span> three <span style="color: green;">girls</span>
        </span>
    </sup>
   </span><br>
   </p>

【问题讨论】:

  • 坏消息,不可能。
  • span 元素的文本和工具提示文本是否已修复?如果是这样,您可以根据引用的元素(跨度)和它自己的大小来定位每个工具提示以适应窗口。否则无法使用 CSS。
  • 您是否考虑过创建额外的工具提示类 - 例如工具提示顶部、工具提示底部并按情况使用它们?
  • 只是为了让您知道我已经用仅 JavaScript 的解决方案更新了我的答案;避免使用 jQuery,文档会更轻。 ⋅⋅⋅ 我看到你真的想要一个纯 CSS 的解决方案,我还添加了一个纯 CSS suggestion 而不修改任何 HTML。

标签: javascript jquery css tooltip


【解决方案1】:

不幸的是,如果您想保持工具提示的良好定位,仅使用 CSS 是不可能的。

脚本解决方案

但是,由于您已经在使用一些脚本,我建议您使用以下解决方案:

  • 使用position: absolute 将.ktooltiptext 定位到.ref,
  • 使用.getBoundingClientRect()方法轻松获取tooltip的位置和大小,
  • 如果超出window,请应用一些更正,
  • 还在 CSS 中做了一些修改。

仅使用原生 JavaScript 的片段(避免使用 jQuery,文档会更轻量。)

var ktooltips = document.querySelectorAll(".ktooltip");
ktooltips.forEach(function(ktooltip, index){                // For each ktooltip
  ktooltip.addEventListener("mouseover", position_tooltip); // On hover, launch the function below
})

function position_tooltip(){
  // Get .ktooltiptext sibling
  var tooltip = this.parentNode.querySelector(".ktooltiptext");
  
  // Get calculated ktooltip coordinates and size
  var ktooltip_rect = this.getBoundingClientRect();

  var tipX = ktooltip_rect.width + 5; // 5px on the right of the ktooltip
  var tipY = -40;                     // 40px on the top of the ktooltip
  // Position tooltip
  tooltip.style.top = tipY + 'px';
  tooltip.style.left = tipX + 'px';

  // Get calculated tooltip coordinates and size
  var tooltip_rect = tooltip.getBoundingClientRect();
  // Corrections if out of window
  if ((tooltip_rect.x + tooltip_rect.width) > window.innerWidth) // Out on the right
    tipX = -tooltip_rect.width - 5;  // Simulate a "right: tipX" position
  if (tooltip_rect.y < 0)            // Out on the top
    tipY = tipY - tooltip_rect.y;    // Align on the top

  // Apply corrected position
  tooltip.style.top = tipY + 'px';
  tooltip.style.left = tipX + 'px';
}
.ref,
.refs {
  position: relative;
}

.ktooltip {
  display: inline-block;
  text-indent: 0em;
}

.ref .ktooltiptext,
.refs .ktooltiptext {
  visibility: hidden;
  width: 200px;
  background: #fff;
  border-radius: 6px;
  padding: 5px;       /* TAKIT: Changed here */
  top: -999px;        /* TAKIT: Changed here */
  left: -999px;       /* TAKIT: Changed here */
  border: 2px solid grey;
  line-height: normal;
  position: absolute; /* TAKIT: Changed here */
  z-index: 1;
}

.ref:hover .ktooltiptext,
.refs:hover .ktooltiptext {
  visibility: visible;
}
<p>
  <span id="edtxt.trans1" class="tei l">My hope is in a bishop,
 <!--link to a reference -->
   <sup class="ref expl">
     <a href="#edtxt-explnote1" id="reference-to-edtxt-explnote1" class="ktooltip">1</a>
       <!-- the reference in a tooltip -->
       <span class="ktooltiptext">According to tradition <span style="name">Nicholas</span> was bishop of Myra in Lycia (south-west Turkey today).</span>
  </sup>
  </span><br>
  <span id="trans2" class="tei l">and in almighty God and his never-ending miracles.</span><br>
  <span id="trans3" class="tei l">Generous Saint Nicholas holds an office,</span><br>
  <span id="trans4" class="tei l">there is a gold symbol in his sign.
    <!-- link to ref -->
    <sup class="ref expl">
      <a href="#edtxt-explnote2" id="reference-to-edtxt-explnote2" class="ktooltip">20</a>
        <!-- the tooltip -->
        <span class="ktooltiptext"> One of <span style="">Nicholas’s</span> symbols was three <sup>bags</sup> of gold <span style="font-variant: small-caps;">which</span> were the <span style="color: red;">dowry</span> he provided <span style="color: blue;">for</span>  three <span style="color: green;">girls</span>
  </span>
  </sup>
  </span><br>
</p>

带有 jQ​​uery 的片段

$(".ktooltip").mouseover(function(e) {
  var tooltip = $(this).siblings('.ktooltiptext'); // Get tooltip element (ktooltiptext)
  var tipX = $(this).outerWidth() + 5;             // 5px on the right of the ktooltip
  var tipY = -40;                                  // 40px on the top of the ktooltip
  tooltip.css({ top: tipY, left: tipX });          // Position tooltip

  // Get calculated tooltip coordinates and size
  var tooltip_rect = tooltip[0].getBoundingClientRect();
  // Corrections if out of window
  if ((tooltip_rect.x + tooltip_rect.width) > $(window).width()) // Out on the right
    tipX = -tooltip_rect.width - 5; // Simulate a "right: tipX" position
  if (tooltip_rect.y < 0)            // Out on the top
    tipY = tipY - tooltip_rect.y;    // Align on the top

  // Apply corrected position
  tooltip.css({ top: tipY, left: tipX }); 
});
.ref,
.refs {
  position: relative;
}

.ktooltip {
  display: inline-block;
  text-indent: 0em;
}

.ref .ktooltiptext,
.refs .ktooltiptext {
  visibility: hidden;
  width: 200px;
  background: #fff;
  border-radius: 6px;
  padding: 5px;       /* TAKIT: Changed here */
  top: -999px;        /* TAKIT: Changed here */
  left: -999px;       /* TAKIT: Changed here */
  border: 2px solid grey;
  line-height: normal;
  position: absolute; /* TAKIT: Changed here */
  z-index: 1;
}

.ref:hover .ktooltiptext,
.refs:hover .ktooltiptext {
  visibility: visible;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>
  <span id="edtxt.trans1" class="tei l">My hope is in a bishop,
 <!--link to a reference -->
   <sup class="ref expl">
     <a href="#edtxt-explnote1" id="reference-to-edtxt-explnote1" class="ktooltip">1</a>
       <!-- the reference in a tooltip -->
       <span class="ktooltiptext">According to tradition <span style="name">Nicholas</span> was bishop of Myra in Lycia (south-west Turkey today).</span>
  </sup>
  </span><br>
  <span id="trans2" class="tei l">and in almighty God and his never-ending miracles.</span><br>
  <span id="trans3" class="tei l">Generous Saint Nicholas holds an office,</span><br>
  <span id="trans4" class="tei l">there is a gold symbol in his sign.
    <!-- link to ref -->
    <sup class="ref expl">
      <a href="#edtxt-explnote2" id="reference-to-edtxt-explnote2" class="ktooltip">20</a>
        <!-- the tooltip -->
        <span class="ktooltiptext"> One of <span style="">Nicholas’s</span> symbols was three <sup>bags</sup> of gold <span style="font-variant: small-caps;">which</span> were the <span style="color: red;">dowry</span> he provided <span style="color: blue;">for</span>  three <span style="color: green;">girls</span>
  </span>
  </sup>
  </span><br>
</p>

使用上面的任何一个sn-ps,你都可以玩你的窗口,看看右边的弹窗不会出去!它也不应该出现在顶部。


⋅ ⋅ ⋅

仅 CSS 建议

现在,如果您不太关心工具提示的位置,您可以在我没有更改任何 HTML 的情况下使用此解决方案:

  • 在span 元素上使用position: relative; 以将其用作参考,
  • 在.ktooltiptext 上使用position: absolute,
  • 根据需要使用top 和left 定位.ktooltiptext。

使用该解决方案,工具提示将保持其样式,但会在左侧对齐,在 span 元素下方,因此工具提示不应出现在右侧或顶部。

p span { /* TAKIT: Changed here */
  position: relative;
}

.ktooltip {
  display: inline-block;
  text-indent: 0em;
}

.ref .ktooltiptext,
.refs .ktooltiptext {
  visibility: hidden;
  width: 200px;
  background: #fff;
  border-radius: 6px;
  padding: 5px;       /* TAKIT: Simplified here */     
  border: 2px solid grey;
  line-height: normal;
  position: absolute; /* TAKIT: Changed */
  top: 20px;          /* TAKIT: Changed */
  left: 0;            /* TAKIT: Added to always align tooltip on the left of the span */ 
  z-index: 1;
}

.ref:hover .ktooltiptext,
.refs:hover .ktooltiptext {
  visibility: visible;
}
<p>
  <span id="edtxt.trans1" class="tei l">My hope is in a bishop,
 <!--link to a reference -->
   <sup class="ref expl">
     <a href="#edtxt-explnote1" id="reference-to-edtxt-explnote1" class="ktooltip">1</a>
       <!-- the reference in a tooltip -->
       <span class="ktooltiptext">According to tradition <span style="name">Nicholas</span> was bishop of Myra in Lycia (south-west Turkey today).</span>
  </sup>
  </span><br>
  <span id="trans2" class="tei l">and in almighty God and his never-ending miracles.</span><br>
  <span id="trans3" class="tei l">Generous Saint Nicholas holds an office,</span><br>
  <span id="trans4" class="tei l">there is a gold symbol in his sign.
    <!-- link to ref -->
    <sup class="ref expl">
      <a href="#edtxt-explnote2" id="reference-to-edtxt-explnote2" class="ktooltip">20</a>
        <!-- the tooltip -->
        <span class="ktooltiptext"> One of <span style="">Nicholas’s</span> symbols was three <sup>bags</sup> of gold <span style="font-variant: small-caps;">which</span> were the <span style="color: red;">dowry</span> he provided <span style="color: blue;">for</span>  three <span style="color: green;">girls</span>
  </span>
  </sup>
  </span><br>
</p>

【讨论】:

  • 这很棒而且效果很好,但是在有很多文本的页面上,无论页面滚动到哪里,弹出窗口都会出现。因此,如果您滚动页面,则弹出窗口与悬停或离开页面不对齐,如果这是加载链接/悬停的页面。
  • @PaulM 我明白你的意思。如果我们放更多的文字,什么元素可以滚动?我们可以知道它被滚动了多少,我们可以相应地补偿工具提示的位置。
  • @PaulM 忘记我上面的问题。我将position 从fixed 修改为absolute 并使用.getBoundingClientRect() 方法来获取我们元素的大小和坐标,以便更正它们。见sn-p。我希望它能满足你的需求。 :)
  • 这里有一些很棒的工作,谢谢 Takit。我已经给了你第一个赏金和正确答案。
  • 现在这里的小改动是不是window.innerWidth被window.visualViewport.width替换了。
【解决方案2】:

你可以只用 CSS 而不用 JS 来试试这个。不是最优雅的工具提示类型,但它永远不会让你失望,也永远不会放弃:)

    .ktooltip {
        display: inline-block;
        text-indent:0em;
    }
    
    .ktooltiptext, .ktooltiptext {
    display: none;
        width: calc(100vw - 35px);
        background: #fff;
        border-radius: 6px;
        padding: 5px 5px;
        left: 10px;
        border: 2px solid grey;
        line-height: normal;
        text-decoration: none;
        position: absolute;
        z-index: 1;
    
    }
    
    p {display:inline-block}
    
    .ktooltip:hover + span {
        display: block;
    }
    <p>
     <span id="edtxt.trans1" class="tei l">My hope is in a bishop,
     <!--link to a reference -->
    <div style="display:inline-block">
      <a href="#edtxt-explnote1" id="reference-to-edtxt-explnote1" class="ktooltip">1</a>
         
    <span class="ktooltiptext">According to tradition <span style="name">Nicholas</span> was bishop of Myra in Lycia (south-west Turkey today).</span>
    </div>
    
      </span><br>
      <span id="trans2" class="tei l">and in almighty God and his never-ending miracles.    </span><br>
      <span id="trans3" class="tei l">Generous Saint Nicholas holds an office,</span><br>
      <span id="trans4" class="tei l">there is a gold symbol in his sign.
        <!-- likn to ref -->
          <a href="#edtxt-explnote2" id="reference-to-edtxt-explnote2" class="ktooltip">2</a>
            <span class="ktooltiptext" onclick="return false;"> One of <span style="">Nicholas’s</span> symbols was three <sup>bags</sup> of gold <span style="font-variant: small-caps;">which</span> were the <span style="color: red;">dowry</span> he provided <span style="color: blue;">for</span> three <span style="color: green;">girls</span>
            </span>
       </span><br>
       </p>

https://jsfiddle.net/gtoprh21/72/

【讨论】:

  • 嗯,它应该是页脚或至少是填充。这是一个非常极端的案例。
  • 有趣的想法,我可以玩弄宽度,而不是进行计算,只需将其设置为 50vw,这样它就不会那么大了。我也可以使用它来将它定位在所有州的页面底部。
  • 这样的好处是真的很轻。您可以从页面中删除大量代码,包括 HTML、CSS 和 JS。如果您在页面上有很多工具提示,它将为您节省几 KB,这对 SEO 来说是一件好事,这是关于网站最重要的事情之一,无论您使用何种技术,没有人愿意制作没有人访问的网站。
  • 我真的很喜欢它的轻盈,所以给了你额外的赏金。它还教会了我在 css 中的大众测量。
  • 谢谢你,你真好。很高兴我能帮上忙。
【解决方案3】:

选项 1) 使用 title 全局属性

title - 指定有关元素的额外信息(显示为 工具提示)

文档:The title global attribute 使用 title 属性是很成问题的:

  • 使用仅触控设备的人
  • 使用键盘导航的人
  • 借助屏幕阅读器或放大镜等辅助技术进行导航的用户
  • 存在精细运动控制障碍的人
  • 有认知问题的人。这主要是由于浏览器支持不一致,加上额外的 辅助技术解析 浏览器呈现的页面。

span {border-bottom: 1px dashed pink}
<span title="According to tradition Nicholas was bishop of Myra in Lycia (south-west Turkey today).">
Mouse over this paragraph, to display the title attribute as a tooltip.
</span>

选项2)如果文本和工具提示文本是固定大小的:可以使用4个css类来放置引用触发元素的工具提示。 比如:

.tooltip-top {top: -3em}
.tooltip-bottom {top: 0}
.tooltip-left {left: -3em}
.tooltip-right {right: 0}

【讨论】:

    【解决方案4】:

    虽然整个事情需要重新编码,但您可以通过以下方式实现:

    $(".ktooltip").on('mouseover', function(e) {
        var tooltip = $('.ktooltiptext'),
            wt = $(window).scrollTop(), //window top pos
            ww = $(window).outerWidth(), //window width
            tt = tooltip.offset().top, //Tooltip top pos
            tl = tooltip.offset().left, //Tooltip left pos
            tw = tooltip.outerWidth(); //Tooltip Width
    
        tooltip.css({ 'left': '10px', 'right': 'auto', 'top': '-40px' });
    
        if(tt < wt) tooltip.css('top', 0);
        if((tl + tw) > ww) tooltip.css({ 'left': 'auto', 'right': 0 });
    })
    

    【讨论】:

      【解决方案5】:

      只需复制此 css 并替换为您的班级

      .ref .ktooltiptext, .refs .ktooltiptext

      .ref .ktooltiptext, .refs .ktooltiptext {
        visibility:hidden;
        width: 200px;
        background: #fff;
        border-radius: 6px;
        padding: 5px 5px;
        top: -15px;
        left: 10px;
        border:2px solid grey;
        line-height: normal;
      
          /* Position the tooltip */
          position: absolute;
          z-index: 1;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-10-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-22
        相关资源
        最近更新 更多