2

TL;DR: Cannot correctly position & display tooltips in a table due to overflow: hidden.

I have created a simple reproducible example of a table whose tooltips are not displaying as intended. The issue exists in part because the table requires overflow: scroll in order for the horizontal scroll of the table to work as intended. Here is an example:

.gap {
  height: 50px
}

div.table { 
  max-width: 200px;

  overflow: scroll;
  border: 2px solid blue;
  display: inline-block;
  font-family: 'Roboto Mono';
  font-weight: 700;
}

.tr {
  display:flex;
}

.td, .th {
  border: 1px solid black;
  min-width: 60px;
  height: 50px;
}

.th {
  position: relative;
  font-size: 13px;
  padding: 2px;
  background-color: #888888;
  text-align: center;
  border-right: 1px solid #555555;
  display: inline-block;
  box-sizing: border-box;
}

.tip-wrapper {
  position: absolute;
}

.tip0 {
  visibility: hidden;
  position: absolute;
  top: -60%;
  z-index: 1;
  max-width: 325px;
  min-width: 160px;
  color: #333333;
  text-align: left;
  background: white;
  border: 1px solid black;
}

.tip1 {
  visibility: hidden;
  position: fixed;
  z-index: 1;
  max-width: 325px;
  min-width: 160px;
  color: #333333;
  text-align: left;
  background: white;
  border: 1px solid black;
}

.tooltip:hover .tip0, .tooltip:hover .tip1 {
  visibility: visible;
}
<div class='gap'>.</div>
<div class='table'>
  <div class='table-headers'>
    <div class='tr'>
      <div class='th tooltip'>
        Z
        <div class='tip0'>
          Heres the ToolTip For Column Z, getting cut off (bad)
        </div>
      </div>
      <div class='th'>Y</div>
      <div class='th tooltip'>
        X
        <div class='tip-wrapper'>
          <div class='tip1'>
            Heres the Tooltip For Column X, which doesn't stay at the top (bad)
          </div>
        </div>
      </div>
      <div class='th'>W</div>
      <div class='th'>V</div>
    </div>
  </div>
  <div class='table-body'>
    <div class='tr'>
    </div>
    <div class='tr'>
      <div class='td stick'>A</div>
      <div class='td'>B</div>
      <div class='td'>C</div>
      <div class='td'>D</div>
      <div class='td'>E</div>
    </div>
    <div class='tr'>
      <div class='td'>F</div>
      <div class='td'>G</div>
      <div class='td'>H</div>
      <div class='td'>I</div>
      <div class='td'>J</div>
    </div>
    <div class='tr'>
      <div class='td'>F</div>
      <div class='td'>G</div>
      <div class='td'>H</div>
      <div class='td'>I</div>
      <div class='td'>J</div>
    </div>
    <div class='tr'>
      <div class='td'>F</div>
      <div class='td'>G</div>
      <div class='td'>H</div>
      <div class='td'>I</div>
      <div class='td'>J</div>
    </div>
    <div class='tr'>
      <div class='td'>F</div>
      <div class='td'>G</div>
      <div class='td'>H</div>
      <div class='td'>I</div>
      <div class='td'>J</div>
    </div>
    <div class='tr'>
      <div class='td'>F</div>
      <div class='td'>G</div>
      <div class='td'>H</div>
      <div class='td'>I</div>
      <div class='td'>J</div>
    </div>
  </div>
</div>

In the table above, the Z and X header cells have tooltips that appear on, however. However, there are issues with both of these tooltips currently:

Column Z: Because of overflow: hidden, this tooltip is getting cut off. It is important that the table can scroll horizontally, so I cannot remove this overflow CSS property. However, its also important that the tooltip hovers above the top of the table, so as to not block the content of the table.

Column X: I tried this approach from this other post. Method 1. This allows the tooltip outside of the overflow: hidden. However, when I scroll this table vertically, the tooltip moves as well, which is not good. The tooltip should remain at the same height always, just above the top of the table.

I was hoping that this basic "tooltips inside the table headers" would work, but it isn't so far. Because of this, I am considering creating a separate tooltip div outside of the table's HTML, and using onMouseOver() and onMouseOut() handler functions to position the tooltip at the mouse location, and populate the tooltip with text. Maybe that is my only approach?

2
  • 1
    Why do you build a fake-table with divs and flex? Commented Jul 15, 2020 at 10:25
  • Has nothing to do with a table. Overflow hidden is a rendering context for its child elements. Why not set the tooltip to position:fixed and then position it based on the table cell's X/Y offset? Commented Jul 16, 2020 at 18:44

4 Answers 4

3
+50

You are missing a .tip-wrapper element on tip0, if you add this and set the top position of .tip-wrapper using calc() to -(th height) - (top threshold in rem) in this case calc(-50px - 1.5rem) then the problem is solved and you have the tooltip placed on top of the table.

You could use dynamic units in th height such as vh, vmax, %. Additionally you would need some @media queries to fine-tune the position of the tooltip.

.td,
.th {
  border: 1px solid black;
  min-width: 10%;
  height: 5vh;
}
.tip-wrapper {
  position: absolute;
  top: calc(-5vh - 1.5rem);
}

.gap {
  height: 100px
}

div.table {
  max-width: 200px;
  overflow: scroll;
  border: 2px solid blue;
  display: inline-block;
  font-family: 'Roboto Mono';
  font-weight: 700;
}

.tr {
  display: flex;
}

.td,
.th {
  border: 1px solid black;
  min-width: 60px;
  height: 50px;
}

.th {
  position: relative;
  font-size: 13px;
  padding: 2px;
  background-color: #888888;
  text-align: center;
  border-right: 1px solid #555555;
  display: inline-block;
  box-sizing: border-box;
}

.tip-wrapper {
  position: absolute;
  top: calc(-50px - 1.5rem);
}

.tip0 {
  visibility: hidden;
  position: fixed;
  z-index: 1;
  max-width: 325px;
  min-width: 160px;
  color: #333333;
  text-align: left;
  background: white;
  border: 1px solid black;
}

.tip1 {
  visibility: hidden;
  position: fixed;
  z-index: 1;
  max-width: 325px;
  min-width: 160px;
  color: #333333;
  text-align: left;
  background: white;
  border: 1px solid black;
}

.tooltip:hover .tip0,
.tooltip:hover .tip1 {
  visibility: visible;
}
<div class='gap'>Gap</div>
<div class='table'>
  <div class='table-headers'>
    <div class='tr'>
      <div class='th tooltip'>
        Z
        <div class='tip-wrapper'>
          <div class='tip0'>
            Tip For Column Z is a long tip with enough text to overflow above the page top
          </div>
        </div>
      </div>
      <div class='th'>Y</div>
      <div class='th tooltip'>
        X
        <div class='tip-wrapper'>
          <div class='tip1'>
            Tip For Column Z is a long tip with enough text to overflow above the page top
          </div>
        </div>
      </div>
      <div class='th'>W</div>
      <div class='th'>V</div>
    </div>
  </div>
  <div class='table-body'>
    <div class='tr'>
    </div>
    <div class='tr'>
      <div class='td stick'>A</div>
      <div class='td'>B</div>
      <div class='td'>C</div>
      <div class='td'>D</div>
      <div class='td'>E</div>
    </div>
    <div class='tr'>
      <div class='td'>F</div>
      <div class='td'>G</div>
      <div class='td'>H</div>
      <div class='td'>I</div>
      <div class='td'>J</div>
    </div>
    <div class='tr'>
      <div class='td'>F</div>
      <div class='td'>G</div>
      <div class='td'>H</div>
      <div class='td'>I</div>
      <div class='td'>J</div>
    </div>
    <div class='tr'>
      <div class='td'>F</div>
      <div class='td'>G</div>
      <div class='td'>H</div>
      <div class='td'>I</div>
      <div class='td'>J</div>
    </div>
    <div class='tr'>
      <div class='td'>F</div>
      <div class='td'>G</div>
      <div class='td'>H</div>
      <div class='td'>I</div>
      <div class='td'>J</div>
    </div>
    <div class='tr'>
      <div class='td'>F</div>
      <div class='td'>G</div>
      <div class='td'>H</div>
      <div class='td'>I</div>
      <div class='td'>J</div>
    </div>
  </div>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

when you scroll vertically down this table, the table header does not stay at the top of the table. that's the problem.
1

Solution

You can mimic your table canvas with a sibling element, then use custom overflow properties on that child to achieve whatever effect you'd like:

document.addEventListener('DOMContentLoaded', _ => {
  const tool = document.querySelector('.tooltip-canvas > tooltip')
  const toolEls = Array.from(document.querySelectorAll('.table [tooltip]'))
  toolEls.forEach(t => {
    t.onmouseenter = _ => {
      tool.setAttribute('tooltip', t.getAttribute('tooltip'))
      tool.style.left = `${t.clientLeft}px`
      tool.style.top = `${t.clientTop - 2}px`
    }
    t.onmouseleave = _ => tool.removeAttribute('tooltip')
  })
})
.gap {
  height: 50px
}

.table-wrap {
  position: relative;
  display: inline-block;
}

.table-wrap > .tooltip-canvas {
  position: absolute;
  pointer-events: none;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.table-wrap > .tooltip-canvas > tooltip {
  content: attr(tooltip);
  position: absolute;
  z-index: 1;
  max-width: 325px;
  min-width: 160px;
  color: #333333;
  text-align: left;
  background: white;
  border: 1px solid black;
  opacity: 0;
  transform: translateY(-100%);
  transition: opacity .25s;
}
.table-wrap > .tooltip-canvas > tooltip[tooltip] {
  opacity: 1;
}

.table-wrap > .tooltip-canvas > tooltip:before {
  content: attr(tooltip)
}

div.table { 
  max-width: 200px;
  overflow: scroll;
  border: 2px solid blue;
  display: inline-block;
  font-family: 'Roboto Mono';
  font-weight: 700;
}

.tr {
  display:flex;
}

.td, .th {
  border: 1px solid black;
  min-width: 60px;
  height: 50px;
}

.th {
  position: relative;
  font-size: 13px;
  padding: 2px;
  background-color: #888888;
  text-align: center;
  border-right: 1px solid #555555;
  display: inline-block;
  box-sizing: border-box;
}
<div class='gap'>.</div>
<section class='table-wrap'>
  <div class='table'>
    <div class='table-headers'>
      <div class='tr'>
        <div class='th' tooltip='Heres the ToolTip For Column Z, getting cut off (bad)'>
          Z
        </div>
        <div class='th'>Y</div>
        <div class='th' tooltip='Heres the Tooltip For Column X, which doesn&spquot;t stay at the top (bad)'>
          X
        </div>
        <div class='th'>W</div>
        <div class='th'>V</div>
      </div>
    </div>
    <div class='table-body'>
      <div class='tr'>
      </div>
      <div class='tr'>
        <div class='td stick'>A</div>
        <div class='td'>B</div>
        <div class='td'>C</div>
        <div class='td'>D</div>
        <div class='td'>E</div>
      </div>
      <div class='tr'>
        <div class='td'>F</div>
        <div class='td'>G</div>
        <div class='td'>H</div>
        <div class='td'>I</div>
        <div class='td'>J</div>
      </div>
      <div class='tr'>
        <div class='td'>F</div>
        <div class='td'>G</div>
        <div class='td'>H</div>
        <div class='td'>I</div>
        <div class='td'>J</div>
      </div>
      <div class='tr'>
        <div class='td'>F</div>
        <div class='td'>G</div>
        <div class='td'>H</div>
        <div class='td'>I</div>
        <div class='td'>J</div>
      </div>
      <div class='tr'>
        <div class='td'>F</div>
        <div class='td'>G</div>
        <div class='td'>H</div>
        <div class='td'>I</div>
        <div class='td'>J</div>
      </div>
      <div class='tr'>
        <div class='td'>F</div>
        <div class='td'>G</div>
        <div class='td'>H</div>
        <div class='td'>I</div>
        <div class='td'>J</div>
      </div>
    </div>
  </div>
  <aside class='tooltip-canvas'>
    <tooltip></tooltip>
  </aside>
</section>

2 Comments

This is the only answer where the tooltip remains at the top of the table when I scroll vertically down the table. The overflow: hidden property is very hard to get around for child elements, and placing the tooltip outside of the table seems like the right idea.
If this worked for you @Canovice, could you mark the answer as completed?
0

Just change the top value in tip0:

.tip0 {
  visibility: hidden;
  position: absolute;
  top: 40%;
  z-index: 1;
  max-width: 325px;
  min-width: 160px;
  color: #333333;
  text-align: left;
  background: white;
  border: 1px solid black;
}

.gap {
  height: 100px
}

div.table { 
  max-width: 200px;

  overflow: scroll;
  border: 2px solid blue;
  display: inline-block;
  font-family: 'Roboto Mono';
  font-weight: 700;
}

.tr {
  display:flex;
}

.td, .th {
  border: 1px solid black;
  min-width: 60px;
  height: 50px;
}

.th {
  position: relative;
  font-size: 13px;
  padding: 2px;
  background-color: #888888;
  text-align: center;
  border-right: 1px solid #555555;
  display: inline-block;
  box-sizing: border-box;
}

.tip-wrapper {
  position: absolute;
}

.tip0 {
  visibility: hidden;
  position: fixed;
  z-index: 1;
  max-width: 325px;
  min-width: 160px;
  color: #333333;
  text-align: left;
  background: white;
  border: 1px solid black;
}

.tip1 {
  visibility: hidden;
  position: fixed;
  z-index: 1;
  max-width: 325px;
  min-width: 160px;
  color: #333333;
  text-align: left;
  background: white;
  border: 1px solid black;
}

.tooltip:hover .tip0, .tooltip:hover .tip1 {
  visibility: visible;
}
<div class='gap'>Gap</div>
<div class='table'>
  <div class='table-headers'>
    <div class='tr'>
      <div class='th tooltip'>
        Z
        <div class='tip0'>
          Tip For Column Z is a long tip with enough text to overflow above the page top
        </div>
      </div>
      <div class='th'>Y</div>
      <div class='th tooltip'>
        X
        <div class='tip-wrapper'>
          <div class='tip1'>
            Tip For Column Z is a long tip with enough text to overflow above the page top
          </div>
        </div>
      </div>
      <div class='th'>W</div>
      <div class='th'>V</div>
    </div>
  </div>
  <div class='table-body'>
    <div class='tr'>
    </div>
    <div class='tr'>
      <div class='td stick'>A</div>
      <div class='td'>B</div>
      <div class='td'>C</div>
      <div class='td'>D</div>
      <div class='td'>E</div>
    </div>
    <div class='tr'>
      <div class='td'>F</div>
      <div class='td'>G</div>
      <div class='td'>H</div>
      <div class='td'>I</div>
      <div class='td'>J</div>
    </div>
    <div class='tr'>
      <div class='td'>F</div>
      <div class='td'>G</div>
      <div class='td'>H</div>
      <div class='td'>I</div>
      <div class='td'>J</div>
    </div>
    <div class='tr'>
      <div class='td'>F</div>
      <div class='td'>G</div>
      <div class='td'>H</div>
      <div class='td'>I</div>
      <div class='td'>J</div>
    </div>
    <div class='tr'>
      <div class='td'>F</div>
      <div class='td'>G</div>
      <div class='td'>H</div>
      <div class='td'>I</div>
      <div class='td'>J</div>
    </div>
    <div class='tr'>
      <div class='td'>F</div>
      <div class='td'>G</div>
      <div class='td'>H</div>
      <div class='td'>I</div>
      <div class='td'>J</div>
    </div>
  </div>
</div>

7 Comments

Thanks but I need the tooltip to hover above-top over the table, not below / inside of the table.
Oh I see you want tool tip to float above the table ?
yes, so it does not block the content in the first few rows of the table.
Check Now and see if it's what you want
I got your point now. I assume the distance from top is correct the thing which is left is that you want it to float while scrolling and not move.
|
0

For tooltip above the table

Remove top attribute and change the position attribute in .tip0 as below

.tip0 {
        visibility: hidden;
        position: fixed;
        margin: -56px -4px;
        z-index: 1;
        max-width: 325px;
        min-width: 160px;
        color: #333333;
        text-align: left;
        background: white;
        border: 1px solid black;
    }

And add margin in .tip1 as below

.tip1 {
    visibility: hidden;
    position: fixed;
    margin: -56px -4px;
    z-index: 1;
    max-width: 325px;
    min-width: 160px;
    color: #333333;
    text-align: left;
    background: white;
    border: 1px solid black;
}

For displaying tooltip within table

Add margin attribute as below inside .tip0 and .tip1 to keep tooltip inside table.

margin: -17px 0px;

and remove top attribute from .tip0

1 Comment

Similar to many other answers, this results in a tooltop that does not stay at the top of the table. Rather, as I scroll down the table, the tooltip scrolls down as well. It does not stay at the top. I appreciate the help but this is not a solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.