Purpose: provide a tooltip that meets the following requirements:
- Is accessible to screen readers
- Is accessible to sighted keyboard users
- Shows on hover and on focus
- Doesn't obstruct other clickable elements
- Gracefully degrades to IE8
<div class="button-list namespace"> | |
<h2>$('selector').tooltip()</h2> | |
<ul> | |
<li> | |
<span>Lorem Ipsum Dolar Sit</span> | |
<button type="button">+ | |
<span class="tooltip" role="tooltip">Hello World again and again and again and again.</span> | |
</button> | |
</li> | |
<li> | |
<span>Lorem Ipsum Dolar Sit</span> | |
<button type="button">+ | |
<span class="tooltip" role="tooltip">Hello World</span> | |
</button> | |
</li> | |
<li> | |
<span>Lorem Ipsum Dolar Sit</span> | |
<button type="button">+ | |
<span class="tooltip" role="tooltip">Hello World</span> | |
</button> | |
</li> | |
<li> | |
<span>Lorem Ipsum Dolar Sit</span> | |
<button type="button">+ | |
<span class="tooltip" role="tooltip">Hello World</span> | |
</button> | |
</li> | |
<li> | |
<span>Lorem Ipsum Dolar Sit</span> | |
<button type="button">+ | |
<span class="tooltip" role="tooltip">Hello World</span> | |
</button> | |
</li> | |
</ul> | |
</div> |
Purpose: provide a tooltip that meets the following requirements:
// Fully accessible tooltip jQuery plugin with delegation. | |
// Ideal for view containers that may re-render content. | |
(function ($) { | |
$.fn.tooltip = function() { | |
this | |
// Delegate to tooltip, Hide if tooltip receives mouse or is clicked (tooltip may stick if parent has focus) | |
.on('mouseenter click', '.tooltip', function (e) { | |
e.stopPropagation(); | |
$(this).removeClass('isVisible'); | |
}) | |
// Delegate to parent of tooltip, Show tooltip if parent receives mouse or focus | |
.on('mouseenter focus', ':has(>.tooltip)', function () { | |
$(this) | |
.find('.tooltip') | |
.addClass('isVisible'); | |
}) | |
// Delegate to parent of tooltip, Hide tooltip if parent loses mouse or focus | |
.on('mouseleave blur', ':has(>.tooltip)', function () { | |
$(this) | |
.find('.tooltip') | |
.removeClass('isVisible'); | |
}); | |
return this; | |
}; | |
}(jQuery)); | |
// Bind event listener to container element | |
$('.namespace').tooltip(); |
html { | |
font-size: 62.5%; | |
} | |
body { | |
font-family: Calibri, Candara, Segoe, 'Segoe UI', Optima, Arial, sans-serif; | |
font-size: 1.6em; | |
} | |
h2 { | |
font-size: 2.4rem; | |
line-height: 1; | |
margin: 0 0 1em; | |
} | |
div { | |
display: inline-block; | |
margin: 1rem; | |
padding: 1rem; | |
border: 1px solid #bcbec0; | |
border-radius: 3px; | |
} | |
ul { | |
display: inline-block; | |
margin: 0; | |
padding: 0; | |
list-style: none; | |
} | |
li { | |
padding: .2em; | |
border-top: 1px solid #ccc; | |
} | |
li:first-child { | |
border-top: none; | |
} | |
button { | |
position: relative; | |
} | |
/* Predefine tooltip styles, content; Hide by default */ | |
.tooltip { | |
position: absolute; | |
box-sizing: border-box; | |
z-index: 2; | |
top: 110%; | |
top: calc(100% + 5px); | |
left: 50%; | |
overflow: hidden; | |
clip: rect(0,0,0,0); | |
width: 1px; | |
height: 1px; | |
padding: 10px 15px; | |
-webkit-transform: translateX(-50%); | |
-ms-transform: translateX(-50%); | |
transform: translateX(-50%); | |
transition: opacity .3s ease-in .3s; | |
font-family: Helvetica, Arial, sans-serif; | |
font-size: 14px; | |
font-size: 1.4rem; | |
text-align: center; | |
white-space: pre; | |
opacity: 0; | |
color: #fff; | |
border: 1px solid #6d6e71; | |
border-top-color: #373739; | |
background-color: #373739; | |
} | |
/* Up arrow */ | |
.tooltip:after { | |
position: absolute; | |
top: -10px; | |
left: 50%; | |
display: block; | |
width: 0; | |
height: 0; | |
margin-left: -10px; | |
content: ' '; | |
pointer-events: none; | |
border-right: 10px solid transparent; | |
border-bottom: 10px solid #373739; | |
border-left: 10px solid transparent; | |
} | |
/* Toggled by jQuery for show/hide */ | |
.tooltip.isVisible { | |
overflow: visible; | |
clip: auto; | |
width: auto; | |
height: auto; | |
opacity: 1; | |
} |