Skip to content

Instantly share code, notes, and snippets.

@CodeMyUI
Created May 1, 2017 04:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CodeMyUI/71c2e9972dda94f7565cd34d616f8f87 to your computer and use it in GitHub Desktop.
Save CodeMyUI/71c2e9972dda94f7565cd34d616f8f87 to your computer and use it in GitHub Desktop.
Simple CSS Tooltips — Interactive Example #codevember
<main>
<div>
<label tooltip="play with the Tooltip text">
<input type="text" value="hello world" />
</label>
<div class="examples">
<p><span tooltip="hello world">Default (up)</span></p>
<p><span tooltip="hello world" flow="up">Pop Up (explicitly)</span></p>
<p><span tooltip="hello world" flow="up-left">Pop Up-Left</span> •
<span tooltip="hello world" flow="up-right">Pop Up-Right</span></p>
<p><span tooltip="hello world" flow="left">Pop Left</span> •
<span tooltip="hello world" flow="right">Pop Right</span></p>
<p><span tooltip="hello world" flow="down-left">Pop Down-Left</span> •
<span tooltip="hello world" flow="down-right">Pop Down-Right</span></p>
<p><span tooltip="hello world" flow="down">Pop Down</span></p>
</div>
</div>
</main>
<aside>
<div>
<textarea cols="30" rows="3" readonly></textarea>
</div>
</aside>
// just helper stuff for example controls
// not needed for actual tooltips
let input = document.querySelector('input')
let output = document.querySelector('textarea')
let main = document.querySelector('.examples')
let tooltips = main.querySelectorAll('[tooltip]')
input.addEventListener('keyup', (e) => {
tooltips.forEach(function(element) {
element.setAttribute('tooltip', e.target.value)
})
})
input.addEventListener('focus', (e) => {
main.classList.add('helper')
})
input.addEventListener('blur', (e) => {
main.classList.remove('helper')
})
document.addEventListener('mouseover', (e) => {
if(e.target.tagName === 'SPAN') {
output.value = e.target.outerHTML
}
})

Simple CSS Tooltips — Interactive Example #codevember

Playing with a way to specify tooltips that get exposed in various directions. Simple attributes controlled via CSS.

A Pen by Jase on CodePen.

License.

:root {
--bg: #353539;
--alt: #ad4375;
--text: #fff;
--opacity: .9;
--accent: #8fd1f2;
--shadow: rgba(0, 0, 0, .35);
--dink: 5px;
--ani: 150ms cubic-bezier(.5, 0, .6, 1.3) 1ms forwards;
}
@keyframes tips-vert {
to {
opacity: var(--opacity);
transform: translate(-50%, 0);
}
}
@keyframes tips-horz {
to {
opacity: var(--opacity);
transform: translate(0, -50%);
}
}
@keyframes tips-diag-right {
to {
opacity: var(--opacity);
transform: translate(-1em, 0);
}
}
@keyframes tips-diag-left {
to {
opacity: var(--opacity);
transform: translate(1em, 0);
}
}
// tooltips
[tooltip] {
position: relative;
&::before,
&::after {
text-transform: none;
line-height: 1;
font-size: .9em;
user-select: none;
pointer-events: none;
position: absolute;
display: none;
opacity: 0;
}
// the dink
&::before {
content: '';
border: var(--dink) solid transparent;
z-index: 1001;
}
// the bubble
&::after {
content: attr(tooltip);
font-family: Helvetica, sans-serif;
text-align: center;
min-width: 3em;
max-width: 21em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding: 1ch 1.5ch;
border-radius: .3em;
box-shadow: 0 1em 2em -.5em var(--shadow);
background: var(--bg);
color: var(--text);
z-index: 1000;
}
// show the tooltip
&:hover::before,
&:hover::after {
display: block;
}
}
[tooltip]:not([flow]),
[tooltip][flow^="up"] {
&::before {
bottom: 100%;
border-bottom-width: 0;
border-top-color: var(--bg);
}
&::after {
bottom: calc(100% + var(--dink));
}
&::before,
&::after {
left: 50%;
transform: translate(-50%, .5em);
}
}
[tooltip][flow^="down"] {
&::before {
top: 100%;
border-top-width: 0;
border-bottom-color: var(--bg);
}
&::after {
top: calc(100% + var(--dink));
}
&::before,
&::after {
left: 50%;
transform: translate(-50%, -.5em);
}
}
[tooltip][flow$="-left"]::after {
right: 50%;
left: auto;
}
[tooltip][flow="up-left"]::after {
transform: translate(1.5em, .5em);
}
[tooltip][flow="down-left"]::after {
transform: translate(1.5em, -.5em);
}
[tooltip][flow="up-right"]::after {
transform: translate(-1.5em, .5em);
}
[tooltip][flow="down-right"]::after {
transform: translate(-1.5em, -.5em);
}
[tooltip][flow="left"] {
&::before {
top: 50%;
border-right-width: 0;
border-left-color: var(--bg);
left: calc(0em - var(--dink));
transform: translate(.5em, -50%);
}
&::after {
top: 50%;
right: calc(100% + var(--dink));
transform: translate(.5em, -50%);
}
}
[tooltip][flow="right"] {
&::before {
top: 50%;
border-left-width: 0;
border-right-color: var(--bg);
right: calc(0em - var(--dink));
transform: translate(-.5em, -50%);
}
&::after {
top: 50%;
left: calc(100% + var(--dink));
transform: translate(-.5em, -50%);
}
}
// FX: do the thing
[tooltip]:not([flow]):hover,
[tooltip][flow^="up"]:hover,
[tooltip][flow^="down"]:hover {
&::before,
&::after {
animation: tips-vert var(--ani);
}
}
[tooltip][flow$="-right"]:hover::after {
animation: tips-diag-right var(--ani);
}
[tooltip][flow$="-left"]:hover::after {
animation: tips-diag-left var(--ani);
}
[tooltip][flow="left"]:hover,
[tooltip][flow="right"]:hover {
&::before,
&::after {
animation: tips-horz var(--ani);
}
}
// don't show empty tooltips
[tooltip=''] {
&::after,
&::before {
display: none !important;
}
}
// BORING
// not related to the tooltips at all,
// just used for presentation of the example
*,
*::before,
*::after {
box-sizing: border-box;
}
html,
body {
height: 100%
}
body {
margin: 0;
display: flex;
font-family: sans-serif;
@media (orientation: portrait) {
flex-direction: column;
}
}
main {
flex: 2;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
background: var(--accent);
@media (orientation: portrait) {
flex: 3;
}
}
aside {
flex: 2;
background: var(--bg);
color: var(--text);
display: flex;
align-items: center;
justify-content: center;
> div {
flex: 1;
}
@media (orientation: landscape) {
flex: 3;
}
}
// show tooltips while editing text
.helper [tooltip] {
--bg: var(--alt);
&::before,
&::after {
display: block;
opacity: .8;
}
}
input {
font: inherit;
font-size: calc(.4em + 1vmin);
color: var(--bg);
text-align: center;
border: .1em solid var(--shadow);
border-radius: .3em;
padding: .5em;
&:focus {
--accent: var(--alt);
outline: none;
border-color: var(--accent);
box-shadow: 0 0 .5em 0 var(--accent) inset, 0 0 .1em 0 var(--accent);
}
}
textarea {
display: block;
font-size: calc(.4em + 1vmin);
text-align: center;
color: var(--text);
width: 100%;
height: 100%;
font-family: monospace;
background: transparent;
border: none;
resize: none;
outline: none;
}
label {
display: inline-block;
padding: 0 0 1em 0;
span {
opacity: .4;
font-size: .8em;
font-style: italic;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment