1

I need to add a hover functionality to labels with overflowing text. Checkout this code pen to find an example of what I mean.

HTML & CSS:

.sku {
  width: 300px;
}

.tooltipp {
  white-space: nowrap;
  overflow-x: hidden;
  text-overflow: ellipsis;
}

.tooltipp:active,
.tooltipp:hover {
  overflow-x: visible;
}

.tooltipp:active span,
.tooltipp:hover span {
  position: relative;
  background-color: PaleGoldenRod;
  border: 1px solid gray;
  padding: 3px;
  margin-left: -4px;
}
<div class="sku tooltipp"><span>Hover over or touch me to see the full version of this string. It looks like replaced by tooltip.</span></div>
<div class="sku tooltipp"><span>Short</span></div>

As you can see in the example the hover is always enabled even if there is no overflow. Is it possible to activate the hover only when there is actual overflowing content?

connexo
  • 53,704
  • 14
  • 91
  • 128
Mulgard
  • 9,877
  • 34
  • 129
  • 232
  • 1
    CSS has nothing to detect if there is actually an overflow or not, you should use javascript to do what you want. – robinvrd Jun 14 '19 at 07:32
  • The accepted answer here looks like a solution to your problem - https://stackoverflow.com/questions/7738117/html-text-overflow-ellipsis-detection – Oliver Trampleasure Jun 14 '19 at 07:46

3 Answers3

2

You should detect overflow using javascript, just compare client and scroll width (can also add height check if overflow-y is hidden).

let skus = document.getElementsByClassName("sku")
for(let sku of skus){
  const overflowing = sku.clientWidth < sku.scrollWidth;
  if(overflowing) sku.classList.add("enable-hover")
}
.sku {
  width:300px;
}

.tooltipp {
  white-space:nowrap;
  overflow-x: hidden;
  text-overflow: ellipsis;
}

.enable-hover:active,
.enable-hover:hover {
  overflow-x: visible;
}

.enable-hover:active span,
.enable-hover:hover span {
  position: relative;
  background-color: PaleGoldenRod;
  border: 1px solid gray;
  padding: 3px;
  margin-left: -4px;
}
<div class="sku tooltipp"><span>Hover over or touch me to see the full version of this string. It looks like replaced by tooltip.</span></div> 
<div class="sku tooltipp"><span>Short</span></div>
Cray
  • 2,774
  • 7
  • 22
  • 32
2

Here is a hacky idea where the trick is to consider a pseudo element that will hide the span in case there is no overflow thus it will prevent the hover/active effect. In case there is overflow, the pseudo element will move to the next line allowing mouse events again.

.sku {
  width: 300px;
  height:1.2em;  /* Make the height equal to height of a line */
  padding:5px;
  z-index:0;
  position:relative;
}

.tooltipp span{
  white-space: nowrap;
  overflow-x: hidden;
  text-overflow: ellipsis;
  display:inline-block;
  max-width:100%;
}

.tooltipp span:active,
.tooltipp span:hover {
  background-color: PaleGoldenRod;
  border: 1px solid gray;
  padding: 3px;
  margin-left: -4px;
  overflow-x: visible;
  max-width:initial;
}
.tooltipp:after {
  content:"";
  height:100%;
  position:relative;
  z-index:1;
  width: 100%;
  margin-left: -99%; /* The magic is here! don't make it 100% or it will also hide the overflowing text */
  display:inline-block;
}
<div class="sku tooltipp"><span>Hover over or touch me to see the full version of this string. It looks like replaced by tooltip.</span></div>
<div class="sku tooltipp"><span>Short</span></div>
<div class="sku tooltipp"><span>Hover over or touch me to see the full version of this string. It looks like replaced by tooltip</span></div>
<div class="sku tooltipp"><span>Short text without hover</span></div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
1

You can use the following Javascript function:

function hasOverflow(element) {
  const elem = element.cloneNode(true);
  elem.style.overflowX = 'visible';
  elem.style.width = 'auto';
  elem.style.visibility = 'hidden';
  elem.style.display = 'inline-block';
  document.body.appendChild(elem);
  const origWidth = parseInt(window.getComputedStyle(element).width);
  const cloneWidth = parseInt(window.getComputedStyle(elem).width);
  const isOverflowing = origWidth < cloneWidth;
  document.body.removeChild(elem);
  return isOverflowing;
}

[...document.querySelectorAll('.sku')].forEach(sku => {
  sku.addEventListener('mouseenter', () => {
    if (hasOverflow(sku)) sku.classList.add('overflow');
    console.log(hasOverflow(sku));
  })
  sku.addEventListener('mouseleave', () => {
    sku.classList.remove('overflow');
  })
})
.sku {
  width: 300px;
}

.tooltipp {
  white-space: nowrap;
  overflow-x: hidden;
  text-overflow: ellipsis;
}

.overflow:active,
.overflow:hover {
  overflow-x: visible;
}

.overflow:active span,
.overflow:hover span {
  position: relative;
  background-color: PaleGoldenRod;
  border: 1px solid gray;
  padding: 3px;
  margin-left: -4px;
}
<div class="sku tooltipp"><span>Hover over or touch me to see the full version of this string. It looks like replaced by tooltip.</span></div>
<div class="sku tooltipp"><span>Short</span></div>
connexo
  • 53,704
  • 14
  • 91
  • 128