Skillversitas

Tooltips

A tooltip is a small element that appears when the user moves the cursor over an element. Tooltips usually display additional information, a short explanation, or a hint about that element. In CSS, a tooltip can be built completely without JavaScript using the ::before and ::after pseudo-elements.

The most common approach is to use a data-tooltip attribute in the HTML, then let CSS display the attribute's content as the tooltip using attr(data-tooltip) on a pseudo-element. The tooltip is positioned absolutely relative to its parent element.

Transitions on opacity and transform provide a smooth animation when the tooltip appears. The tooltip arrow is created using the border trick on a second pseudo-element.

Code Example

<!DOCTYPE html>
<html lang="en">
<head>
<style>
  body {
    font-family: Arial, sans-serif;
    padding: 60px 40px;
    background: #f5f5f5;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 40px;
  }

  /* Base Tooltip */
  [data-tooltip] {
    position: relative;
    cursor: pointer;
  }

  [data-tooltip]::before,
  [data-tooltip]::after {
    position: absolute;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s, transform 0.2s, visibility 0.2s;
    pointer-events: none;
    z-index: 1000;
  }

  [data-tooltip]::before {
    content: attr(data-tooltip);
    background: #333;
    color: white;
    padding: 6px 12px;
    border-radius: 6px;
    font-size: 0.85em;
    white-space: nowrap;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%) translateY(5px);
  }

  [data-tooltip]::after {
    content: '';
    border: 6px solid transparent;
    border-top-color: #333;
    bottom: calc(100% - 4px);
    left: 50%;
    transform: translateX(-50%) translateY(5px);
  }

  [data-tooltip]:hover::before,
  [data-tooltip]:hover::after {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
  }

  /* Tooltip Bottom */
  [data-tooltip-bottom]::before {
    bottom: auto;
    top: calc(100% + 8px);
    transform: translateX(-50%) translateY(-5px);
  }

  [data-tooltip-bottom]::after {
    border-top-color: transparent;
    border-bottom-color: #333;
    bottom: auto;
    top: calc(100% - 4px);
    transform: translateX(-50%) translateY(-5px);
  }

  [data-tooltip-bottom]:hover::before,
  [data-tooltip-bottom]:hover::after {
    transform: translateX(-50%) translateY(0);
  }

  /* Tooltip Left */
  [data-tooltip-left]::before {
    bottom: auto;
    top: 50%;
    right: calc(100% + 8px);
    left: auto;
    transform: translateY(-50%) translateX(5px);
  }

  [data-tooltip-left]::after {
    border-top-color: transparent;
    border-left-color: #333;
    bottom: auto;
    top: 50%;
    right: calc(100% - 4px);
    left: auto;
    transform: translateY(-50%) translateX(5px);
  }

  [data-tooltip-left]:hover::before,
  [data-tooltip-left]:hover::after {
    transform: translateY(-50%) translateX(0);
  }

  /* Tooltip Right */
  [data-tooltip-right]::before {
    bottom: auto;
    top: 50%;
    left: calc(100% + 8px);
    transform: translateY(-50%) translateX(-5px);
  }

  [data-tooltip-right]::after {
    border-top-color: transparent;
    border-right-color: #333;
    bottom: auto;
    top: 50%;
    left: calc(100% - 4px);
    transform: translateY(-50%) translateX(-5px);
  }

  [data-tooltip-right]:hover::before,
  [data-tooltip-right]:hover::after {
    transform: translateY(-50%) translateX(0);
  }

  /* Demos */
  .demo-box {
    background: white;
    padding: 30px;
    border-radius: 12px;
    box-shadow: 0 2px 10px rgba(0,0,0,0.08);
    text-align: center;
    width: 350px;
  }

  .demo-box h3 {
    margin-top: 0;
    color: #333;
  }

  .icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: #667eea;
    color: white;
    font-size: 1.2em;
    margin: 0 5px;
    transition: background 0.2s;
  }

  .icon-btn:hover {
    background: #5a6fd6;
  }

  .info-link {
    color: #667eea;
    border-bottom: 1px dashed #667eea;
    padding-bottom: 2px;
  }

  .form-group {
    text-align: left;
    margin: 15px 0;
  }

  .form-group label {
    display: block;
    margin-bottom: 5px;
    font-weight: bold;
    color: #555;
  }

  .form-group input {
    width: 100%;
    padding: 10px 12px;
    border: 2px solid #ddd;
    border-radius: 8px;
    font-size: 1em;
    box-sizing: border-box;
    transition: border-color 0.2s;
  }

  .form-group input:focus {
    outline: none;
    border-color: #667eea;
  }

  .help-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #ddd;
    color: #666;
    font-size: 0.7em;
    font-weight: bold;
    margin-left: 5px;
    cursor: help;
  }

  .directions {
    display: flex;
    gap: 15px;
    flex-wrap: wrap;
    justify-content: center;
  }
</style>
</head>
<body>
  <div class="demo-box">
    <h3>Tooltip Dasar</h3>
    <p>Hover the cursor over the element below:</p>
    <span data-tooltip="This is a tooltip!" class="info-link">
      Hover me
    </span>
  </div>

  <div class="demo-box">
    <h3>Icon Buttons</h3>
    <span data-tooltip="Share" class="icon-btn">📤</span>
    <span data-tooltip="Sukai" class="icon-btn">❤️</span>
    <span data-tooltip="Komentar" class="icon-btn">💬</span>
    <span data-tooltip="Save" class="icon-btn">🔖</span>
  </div>

  <div class="demo-box">
    <h3>Form with Tooltips</h3>
    <div class="form-group">
      <label>Email <span class="help-icon" data-tooltip="We will not share your email">?</span></label>
      <input type="email" placeholder="[email protected]">
    </div>
    <div class="form-group">
      <label>Password <span class="help-icon" data-tooltip="At least 8 characters, must include letters and digits">?</span></label>
      <input type="password" placeholder="Enter password">
    </div>
  </div>

  <div class="demo-box">
    <h3>Tooltip Direction</h3>
    <div class="directions">
      <span data-tooltip="Top" class="icon-btn">↑</span>
      <span data-tooltip-bottom="Bottom" class="icon-btn">↓</span>
      <span data-tooltip-left="Left" class="icon-btn">←</span>
      <span data-tooltip-right="Right" class="icon-btn">→</span>
    </div>
  </div>
</body>
</html>

Code Explanation

[data-tooltip]::before: The before pseudo-element displays the tooltip text from the data-tooltip attribute using attr(data-tooltip). This allows every element to have its own tooltip without duplicating HTML.

[data-tooltip]::after: The after pseudo-element creates the arrow of the tooltip using the border trick. The border size determines the arrow size.

position: absolute: The tooltip is positioned relative to the parent that has position: relative. This ensures the tooltip appears in the correct position.

opacity and visibility transitions: Transitions on opacity and visibility provide a smooth animation as the tooltip appears and disappears. Transform adds a subtle sliding effect.

pointer-events: none: Prevents the tooltip from interfering with mouse interaction on the element. Without this, the tooltip could block hover in certain areas.

data-tooltip-bottom/left/right: Modifiers that change the direction of the tooltip. Each direction requires adjustments to the position and the arrow's direction.

Everyday Use Cases

Icon navigation: Every icon in a navbar can have a tooltip explaining its function, especially for icons that have no text label.

Form help: A form field can have a tooltip with hints about the expected input format, such as password requirements.

Data table: A table column header can have a tooltip explaining the meaning of an abbreviation or the metric being used.

Toolbar: Buttons in an editor toolbar can have tooltips explaining keyboard shortcuts.

Conclusion

CSS tooltips are built with the ::before and ::after pseudo-elements plus a data-tooltip attribute. Transitions on opacity and transform provide the animation. The arrow is created with the border trick. This approach is pure CSS without JavaScript — lightweight and easy to maintain. For more complex tooltips with HTML formatting, consider a library or a JavaScript approach.