Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <html>
<body data-controller="tooltip">
  <div id="tooltip" style="display: none;" data-target="tooltip.tooltip" class="tooltip">
      Tooltip with some medium info
  </div>
  <span class="indented" data-action="mouseover->tooltip#show mouseout->tooltip#hide" data-tooltip-msg="This should show below instead" data-tooltip-above="-20">
    Close to the top
  </span>
  
  <div class="blank-space">
  </div>
  
    <div class="indented">
      <span class="block margin" data-action="mouseover->tooltip#show mouseout->tooltip#hide" data-tooltip-msg="Short and slightly more above" data-tooltip-above="50">
        A long sentence that we want to show something above
      </span>
    </div>
      
    <div class="indented">
      <span data-action="mouseover->tooltip#show mouseout->tooltip#hide" class="block margin" data-tooltip-msg="This message is still perfectly centered">
        A short sentence
      </span>
    </div>

  <span class="margin" data-action="mouseover->tooltip#show mouseout->tooltip#hide" data-tooltip-msg="This message isn't clipped and not centered">I'm close to the left</span>
  
  <div class="blank-space"></div>
  
  <div class="indented">
    <span data-action="mouseover->tooltip#show mouseout->tooltip#hide"
          data-tooltip-msg="This should show up just above">
      At the bottom of the page
    </span>
  </div>
    
  </div>
</body>
</html>
              
            
!

CSS

              
                .blank-space {
  height: 200px;
  width: 100%;
}

.indented {
  margin-left: 100px;
  position: relative;
}

.block {
  display: inline-block;
}


.margin {
  margin: 20px 0;
} 

.tooltip {
  border: 1px dotted #AAA;
  position: absolute;
  padding: 5px;
  border-radius: 3px;
}
              
            
!

JS

              
                const application = Stimulus.Application.start();

class TooltipController extends Stimulus.Controller {
  // The tooltip controller assumes that the tooltip element isn't
  // contained by any element or parent element that has "position: relative"
  // If that is the case the positioning of the tooltip WILL break.

  // create an element <div data-target="tooltip.tooltip"></div>
  // this element will be filled with text.

  // for any element that should have a tooltip do the following
  // <span
  //  data-tooltip-msg="My tooltip message"
  //  data-action="mouseover->tooltip#show mouseout->tooltip#hide"
  //  data-tooltip-above="30"
  // ></span>

  // data-tooltip-msg -> The message that the tooltip should display
  // data-tooltip-width -> Width of tooltip
  // data-tooltip-above -> How many pixels above the parent element the tooltip should be
  //                       by default this is 30px.
  static targets = [ "tooltip" ]
  
  show(event) {
    const dataset = event.target.dataset
    let above = Number(event.target.dataset.tooltipAbove ? event.target.dataset.tooltipAbove : 30)
    let tooltip = this.tooltipTarget
    tooltip.innerHTML = event.target.dataset.tooltipMsg
    // re-paint before getting coordinates from tooltip
    let width = dataset.tooltipWidth ? `width: ${dataset.tooltipWidth}px` : ''
    tooltip.style = `display: block; ${width};`
    
    const ttLoc = tooltip.getBoundingClientRect()
    // getBoundingClientRect is viewport coordinates we need
    // height if we've scrolled. 
    const scroll = document.documentElement.scrollTop
    
    let targetPos = event.target.getBoundingClientRect()
    let yLoc = targetPos.y + scroll - above
    let xLoc = targetPos.x + targetPos.width / 2 - ttLoc.width / 2
    xLoc = xLoc < 0 ? 0 : xLoc
    
    tooltip.style = `position: absolute; top: ${yLoc}px; left: ${xLoc}px;`
  }
  
  hide(event) {
    let tooltip = this.tooltipTarget
    tooltip.style = 'display: none;'
  }
  
}

application.register("tooltip", TooltipController);
              
            
!
999px

Console