0

I am creating a tooltip for a web app using just CSS. So far I've got a pretty handy tooltip going with the following classes:

  • tooltip-up
  • tooltip-down
  • tooltip-left
  • tooltip-right

The difference with each is the arrow and the animation. The class 'tooltip-right' for example has the arrow towards the left side and it animated from the left, towards the right.

enter image description here

The issue comes when the tooltip has lots of text, the tooltip-left, -right, and -up all position differently when there is lots of text in the tooltip. Tooltip down has no issues because everything wraps downward by default.

enter image description here

So my question is, is it possible to perfectly position the tooltip with just CSS. Or will some JS be involved, if so, what do you suggest to do? Maybe add check to see how much text a tooltip has and add some inline css for margin? As an example, I was trying to replicate http://foundation.zurb.com/sites/docs/v/5.5.3/components/tooltips.html, we are using foundation but there seems to be some issue with it and Angular.

Here's some code I have so far:

  .tooltip-up,
  .tooltip-down,
  .tooltip-left,
  .tooltip-right {
    font-size: 12px;
    position: absolute;
    text-align: center!important;
    visibility: hidden;
    background-color: rgba($gray, 0.99);
    color: #fff;
    text-align: left;
    border-radius: 3px;
    width: 250px;
    height: auto;
    padding: 7px 10px;
    z-index: 1;
    opacity: 0;
    box-shadow: 0 2px 5px 0 rgba($solid-black, 0.16), 0 2px 10px 0 rgba($solid-black, 0.12);
    @include transition (.2s ease-in);
  }

  .tooltip-right {
    top: -35%;
    left: 135%;
    transform: translateX(-15%);
    margin-top: -10px;

    &:after {
      border-right: 7px solid rgba($gray, 0.99);
      border-bottom: 7px solid transparent;
      border-top: 7px solid transparent;
      top: 50%;
      content: " ";
      height: 0;
      left: -7px;
      position: absolute;
      width: 0;
      transform: translateY(-50%);
    }

  }

Please keep in mind that there are four tooltip classes, so your solution must take into account the tool tip left, right, and top as well. Thanks for any info and help beforehand.

2 Answers 2

1

You can use the same trick you've already used to position the arrow: use translateY(-50%) in combination with position: absolute and top: 50%.

Since the 50% is relative to the tooltip, it will always remain centered. Two pitfalls:

  • watch out that you don't translate the tooltip out of view
  • sometimes, text can get blurry if the height is an odd pixel size. E.g.: height 27px will move the tooltip 13.5px down.

p { display: inline-block; position: relative; border: 1px solid red; }

.tooltip-right {
  box-sizing: border-box;
  font-size: 12px;
  position: absolute;
  text-align: center;
  background-color: black;
  color: #fff;
  text-align: left;
  border-radius: 3px;
  width: 250px;
  padding: 7px 10px;
  z-index: 1;
  opacity: .8;
  
  top: 50%;
  right: 0;
  /* width + arrow width = 250 + 7 = 257 */
  transform: translate3d(257px, -50%, 0);
}

.tooltip-right::after {
  content: "";

  border-right: 7px solid black;
  border-bottom: 7px solid transparent;
  border-top: 7px solid transparent;
  
  position: absolute;
  height: 0;
  width: 0;
  left: -7px;
  top: 50%;
 
  transform: translateY(-50%);
}
<h2>Use translateY for positioning</h2>
<p>
  <span>
    Lorem ipsum
  </span>
  <span class="tooltip-right">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
  </span>
</p>

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

4 Comments

thank you for the answer, if you can could you comment your code? I tried implementing your answer but it doesn't seem to work for me.
Also, in regards to using translate Y 50% along side top 50%, im already using translate X for the animation from left to right, so if I added a translate Y the animation will include it in the Y axis as well, and that looks weird to the user.
You can transform from translateY(-50%) translateX(0) to translateY(-50%) translateX(15px) and only the horizontal translation will be animated. The basic principle is this: the callouts gets positioned on the right of its parent, 50% down. Using transform, you put it back up half its own height, and you move it its full width right. You can use your browser's web inspector to toggle rules on and off to see what they do.
I kinda get it but I thought a transform would overwrite the last, can you update your code please so I can see how to use? :)
0

Try:

.tooltip-up,
.tooltip-down,
.tooltip-left,
.tooltip-right {
    font-size: 12px; /* I think you should use the unit em instead for better scaling */
    position: absolute;
    text-align: center!important; /* why !important ? */
    visibility: hidden; /* I think you should remove this line since you set opacity to 0 */
    background-color: rgba($gray, 0.99);
    color: #fff;
    text-align: left; /* I think you should remove this line */
    border-radius: 3px;
    width: 250px; /* I think you should use the unit em instead */
    height: auto; /* I think you should remove this line, for auto is the default value */
    padding: 7px 10px; /* I think you should use the unit em instead */
    z-index: 1; /* I think you should set this to the next greatest value in your code, just in case */
    opacity: 0;
    box-shadow: 0 2px 5px 0 rgba($solid-black, 0.16), 0 2px 10px 0 rgba($solid-black, 0.12);
    @include transition (.2s ease-in);
}

.tooltip-right {
    top: -35%;
    left: 135%;
    transform: translateX(-15%);
    margin-top: -10px;

&:after {
    border-right: 7px solid rgba($gray, 0.99);
    border-bottom: 7px solid transparent;
    border-top: 7px solid transparent;
    top: 1em; /* Try what works best, but don't use % because when there's a lot of text, the arrow would fall off place */
    content: "";
    height: 0;
    left: -7px;
    position: absolute;
    width: 0;
    transform: translateY(-50%);
}

}

1 Comment

Hi thanks for your comments, some of CSS has to be there like that to avoid conflict with legacy code, I've fixed a bit of the things I could remove, thanks.

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.