Playing with a way to specify tooltips that get exposed in various directions. Simple attributes controlled via CSS.
Created
May 1, 2017 04:28
-
-
Save CodeMyUI/71c2e9972dda94f7565cd34d616f8f87 to your computer and use it in GitHub Desktop.
Simple CSS Tooltips — Interactive Example #codevember
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 | |
} | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
: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