Tooltips provide brief information messaging through a mouse or keyboard hover.
Use tool tips to provide additional information. Don't use tooltips for that is required to complete an interaction as the information disappears when it loses the hover state.
Use tooltips to help differentiate between multiple, close, similar options.
Currently, there is no easy way to activate a hover without with pure CSS without using a keyboard or mouse. Level4 media queries aim to solve that.
Either form works. Place this inside another element for the tooltip to be 'linked to that element.' A container element may need to be added for a single tag element, such as a input field.
Tool tip positions are:
Link with a tool tipTool tip content
Link with a tool tipTool tip content
a(href="#") Link with a tool tip span(role="tooltip" inert tip-position="right") Tool tip content
/* Position Options - top / block-start - right / inline-end - bottom / block-end - left / inline-start */ [role=tooltip] { background: #fff; border-radius: 0.5rem; color: #000; -webkit-filter: drop-shadow(0 3px 3px hsla(0, 0%, 0%, 0.15)) drop-shadow(0 12px 12px hsla(0, 0%, 0%, 0.15)); filter: drop-shadow(0 3px 3px hsla(0, 0%, 0%, 0.15)) drop-shadow(0 12px 12px hsla(0, 0%, 0%, 0.15)); font-size: 1rem; font-weight: 400; inline-size: -webkit-max-content; inline-size: -moz-max-content; inline-size: max-content; line-height: initial; margin: 0; max-inline-size: 25rem; opacity: 0; padding: 0.75rem 1.5rem; pointer-events: none; position: absolute; text-align: start; -webkit-transform: translate(var(--tooltip-x, 0)) translateY(var(--tooltip-y, 0)); -ms-transform: translate(var(--tooltip-x, 0)) translateY(var(--tooltip-y, 0)); transform: translate(var(--tooltip-x, 0)) translateY(var(--tooltip-y, 0)); -webkit-transition: opacity 0.2s ease, -webkit-transform 0.2s ease; transition: opacity 0.2s ease, -webkit-transform 0.2s ease; transition: opacity 0.2s ease, transform 0.2s ease; transition: opacity 0.2s ease, transform 0.2s ease, -webkit-transform 0.2s ease; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; will-change: filter; z-index: 10; } [role=tooltip]::before { clip-path: inset(50%); clip: rect(1px, 1px, 1px, 1px); content: "; Has tooltip: "; height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } [role=tooltip]::after { background: #fff; content: ""; inset: 0; -webkit-mask: var(--tooltip-pointer); mask: var(--tooltip-pointer); position: absolute; z-index: -1; } [role=tooltip]:is([tip-position=top], [tip-position=block-start], :not([tip-position]), [tip-position=bottom], [tip-position=block-end]) { text-align: center; } [role=tooltip]:is([tip-position=top], [tip-position=block-start], :not([tip-position])) { inset-inline-start: 50%; inset-block-end: calc(100% + 0.75rem + 1rem); --tooltip-x: calc(50% * -1); } [role=tooltip]:is([tip-position=top], [tip-position=block-start], :not([tip-position]))::after { --tooltip-pointer: conic-gradient(from -30deg at bottom, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) bottom/100% 50% no-repeat; inset-block-end: -1rem; -webkit-border-after: 1rem solid transparent; border-block-end: 1rem solid transparent; } [role=tooltip]:is([tip-position=right], [tip-position=inline-end]) { inset-inline-start: calc(100% + 1.5rem + 1rem); inset-block-end: 50%; --tooltip-y: 50%; } [role=tooltip]:is([tip-position=right], [tip-position=inline-end])::after { --tooltip-pointer: conic-gradient(from 60deg at left, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) left/50% 100% no-repeat; inset-inline-start: -1rem; -webkit-border-start: 1rem solid transparent; border-inline-start: 1rem solid transparent; } [role=tooltip]:is([tip-position=bottom], [tip-position=block-end]) { inset-inline-start: 50%; inset-block-start: calc(100% + 0.75rem + 1rem); --tooltip-x: calc(50% * -1); } [role=tooltip]:is([tip-position=bottom], [tip-position=block-end])::after { --tooltip-pointer: conic-gradient(from 150deg at top, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) top/100% 50% no-repeat; inset-block-start: -1rem; -webkit-border-before: 1rem solid transparent; border-block-start: 1rem solid transparent; } [role=tooltip]:is([tip-position=left], [tip-position=inline-start]) { inset-inline-end: calc(100% + 1.5rem + 1rem); inset-block-end: 50%; --tooltip-y: 50%; } [role=tooltip]:is([tip-position=left], [tip-position=inline-start])::after { --tooltip-pointer: conic-gradient(from -120deg at right, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) right/50% 100% no-repeat; inset-inline-end: -1rem; -webkit-border-end: 1rem solid transparent; border-inline-end: 1rem solid transparent; } @media (prefers-color-scheme: dark) { [role=tooltip] { background: #1f2127; color: #fff; -webkit-filter: drop-shadow(0 3px 3px hsla(0, 0%, 0%, 0.5)) drop-shadow(0 12px 12px hsla(0, 0%, 0%, 0.5)); filter: drop-shadow(0 3px 3px hsla(0, 0%, 0%, 0.5)) drop-shadow(0 12px 12px hsla(0, 0%, 0%, 0.5)); } [role=tooltip]::after { background: #1f2127; } } :has(> [role=tooltip]) { position: relative; } :has(> [role=tooltip]):is(:hover, :focus-visible, :active) > [role=tooltip] { opacity: 1; -webkit-transition-delay: 300ms; transition-delay: 300ms; } @media (prefers-reduced-motion: no-preference) { :has(> [role=tooltip]:is([tip-position=top], [tip-position=block-start], :not([tip-position]))):not(:hover):not(:active) [role=tooltip] { --tooltip-y: 3px; } :has(> [role=tooltip]:is([tip-position=right], [tip-position=inline-end])):not(:hover):not(:active) [role=tooltip] { --tooltip-x: calc(-1 * -3px * -1); } :has(> [role=tooltip]:is([tip-position=bottom], [tip-position=block-end])):not(:hover):not(:active) [role=tooltip] { --tooltip-y: -3px; } :has(> [role=tooltip]:is([tip-position=left], [tip-position=inline-start])):not(:hover):not(:active) [role=tooltip] { --tooltip-x: calc(-1 * 3px * -1); } }
//- DS2 core (c) 2024 Alexander McIlwraith //- Licensed under CC BY-SA 4.0 $tooltip-border-radius: .5rem !default; $tooltip-dark-allow: true !default; $tooltip-dark-background: #1f2127 !default; $tooltip-dark-drop-shadow: drop-shadow(0 3px 3px hsl(0 0% 0% / 50%)) drop-shadow(0 12px 12px hsl(0 0% 0% / 50%)) !default; $tooltip-dark-foreground: #fff !default; $tooltip-light-background: #fff !default; $tooltip-light-drop-shadow: drop-shadow(0 3px 3px hsl(0 0% 0% / 15%)) drop-shadow(0 12px 12px hsl(0 0% 0% / 15%)) !default; $tooltip-light-foreground: #000 !default; $tooltip-padding-sides: 1.5rem !default; $tooltip-padding-top-bottom: 0.75rem !default; $tooltip-pointer-size: 1rem !default; $tooltip-pointer-bottom: conic-gradient(from -30deg at bottom, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) bottom / 100% 50% no-repeat !default; $tooltip-pointer-left: conic-gradient(from 60deg at left, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) left / 50% 100% no-repeat !default; $tooltip-pointer-right: conic-gradient(from -120deg at right, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) right / 50% 100% no-repeat !default; $tooltip-pointer-top: conic-gradient(from 150deg at top, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) top / 100% 50% no-repeat !default; /* Position Options - top / block-start - right / inline-end - bottom / block-end - left / inline-start */ @mixin tooltip { [role="tooltip"] { background: $tooltip-light-background; border-radius: $tooltip-border-radius; color: $tooltip-light-foreground; filter: $tooltip-light-drop-shadow; font-size: 1rem; font-weight: 400; inline-size: max-content; line-height: initial; margin: 0; max-inline-size: 25rem; opacity: 0; padding: $tooltip-padding-top-bottom $tooltip-padding-sides; pointer-events: none; position: absolute; text-align: start; transform: translate(var(--tooltip-x, 0)) translateY(var(--tooltip-y, 0)); transition: opacity 0.2s ease, transform 0.2s ease; user-select: none; will-change: filter; z-index: 10; &::before { clip-path: inset(50%); clip: rect(1px, 1px, 1px, 1px); content: "; Has tooltip: "; height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } &::after { background: $tooltip-light-background; content: ""; inset: 0; mask: var(--tooltip-pointer); position: absolute; z-index: -1; } &:is( [tip-position="top"], [tip-position="block-start"], :not([tip-position]), [tip-position="bottom"], [tip-position="block-end"] ) { text-align: center; } &:is( [tip-position="top"], [tip-position="block-start"], :not([tip-position]) ) { inset-inline-start: 50%; inset-block-end: calc(100% + $tooltip-padding-top-bottom + $tooltip-pointer-size); --tooltip-x: calc(50% * -1); &::after { --tooltip-pointer: #{$tooltip-pointer-bottom}; inset-block-end: calc($tooltip-pointer-size * -1); border-block-end: $tooltip-pointer-size solid transparent; } } &:is( [tip-position="right"], [tip-position="inline-end"] ) { inset-inline-start: calc(100% + $tooltip-padding-sides + $tooltip-pointer-size); inset-block-end: 50%; --tooltip-y: 50%; &::after { --tooltip-pointer: #{$tooltip-pointer-left}; inset-inline-start: calc($tooltip-pointer-size * -1); border-inline-start: $tooltip-pointer-size solid transparent; } } &:is( [tip-position="bottom"], [tip-position="block-end"] ) { inset-inline-start: 50%; inset-block-start: calc(100% + $tooltip-padding-top-bottom + $tooltip-pointer-size); --tooltip-x: calc(50% * -1); &::after { --tooltip-pointer: #{$tooltip-pointer-top}; inset-block-start: calc($tooltip-pointer-size * -1); border-block-start: $tooltip-pointer-size solid transparent; } } &:is( [tip-position="left"], [tip-position="inline-start"] ) { inset-inline-end: calc(100% + $tooltip-padding-sides + $tooltip-pointer-size); inset-block-end: 50%; --tooltip-y: 50%; &::after { --tooltip-pointer: #{$tooltip-pointer-right}; inset-inline-end: calc($tooltip-pointer-size * -1); -webkit-border-end: $tooltip-pointer-size solid transparent; border-inline-end: $tooltip-pointer-size solid transparent; } } @if ($tooltip-dark-allow == true ) { @media (prefers-color-scheme: dark) { background: $tooltip-dark-background; color: $tooltip-dark-foreground; filter: $tooltip-dark-drop-shadow; &::after { background: $tooltip-dark-background; } } } } :has(> [role="tooltip"]) { position: relative; &:is(:hover, :focus-visible, :active) > [role="tooltip"] { opacity: 1; transition-delay: 300ms; } } @media (prefers-reduced-motion: no-preference) { :has(> [role="tooltip"]:is([tip-position="top"], [tip-position="block-start"], :not([tip-position]))):not(:hover):not(:active) [role="tooltip"] { --tooltip-y: 3px; } :has(> [role="tooltip"]:is([tip-position="right"], [tip-position="inline-end"])):not(:hover):not(:active) [role="tooltip"] { --tooltip-x: calc(-1 * -3px * -1); } :has(> [role="tooltip"]:is([tip-position="bottom"], [tip-position="block-end"])):not(:hover):not(:active) [role="tooltip"] { --tooltip-y: -3px; } :has(> [role="tooltip"]:is([tip-position="left"], [tip-position="inline-start"])):not(:hover):not(:active) [role="tooltip"] { --tooltip-x: calc(-1 * 3px * -1); } } }