Directly above

Analyze the execution process

  1. Move the mouse to the node
  2. Check whether the node has enabled implementationtooltipThe identity of the implementation (class name, attributes, etc.)
  3. Detect subject, location (class name, attribute, etc.)
  4. Generate/display bubbles

Learn from others

Let’s start by looking at the Tooltip style of Element-UI

Obviously, the location of the bubble is added via javascript


Let’s set some expectations

  1. Don’t have tojavascript, purecssImplementation;
  2. You don’t have to add new elements(Use after, before pseudo-elements)
  3. Instead of class name matching, use the property selector directly[attr]
  4. Support default styles (tags without theme or location)
  5. Instruction (directly in the label definition, next to thecssMatch)
  6. Implement the theme and location of the bubble
  7. withsassPreprocessor development

HTML definition instruction specification

Directive declaration:

<button tooltip='I'm a content duck' effect='light' placement='top-left'> on the left < / button >Copy the code
  • tooltip– Contents displayed by bubbles;
  • effect— Bubble theme (Dark/light), dark by default;
  • placement— The position of the bubble relative to the parent (top/ top-left/ top-right/right/right-top/ right-bottom…) , default top;

Let’s write a few buttons

The style borrows from Element-UI

<div class="container">
  <div class="top">
    <button tooltip="Above" placement="top-left" effect="light"> left </button> <button tooltip="Top left, top left." placement="top"> top </button> <button tooltip="Right" placement="top-right"</button> </div> <div class="left">
    <button tooltip="Top left, top left, top left, top left, top left, top left, top left, top left, top left." placement="left-top"> upper left </button> <button tooltip="The left" placement="left" effect="light"> left </button> <button tooltip="About" placement="left-bottom"</button> </div> <div class="right">
    <button tooltip="Top right, top right, top right, top right, top right, top right, top right, top right, top right, top right." placement="right-top"</button> <button tooltip="The right" placement="right" effect="light"> Right </button> <button tooltip="Right" placement="right-bottom"</button> </div> <div class="bottom">
    <button tooltip="Down left down left." placement="bottom-left"</button> <button tooltip="Bottom" placement="bottom" effect="light"</button> <button tooltip="Right" placement="bottom-right"</button> </div>Copy the code

CSS core code logic implementation

Hover listener, [tooltip] matches tags with this attribute, after is a bubble, before is a triangle:

/* Match elements with tooltip attributes */ [tooltip] {position: relative; /* Bubble default style */ &::after {display: none; content: attr(tooltip); } /* Triangle default style */ &::before {display: none; content:' '; } /* Hover {&::after {display: block; } &::before { display: block; }}}Copy the code

Now it works after mouse over


To make it easier to see, tests can default bubbles and triangles to blocks

/* Bubble default style */ &::after {display: block; content: attr(tooltip); } /* Triangle default style */ &::before {display: block; content:' ';
}
Copy the code

The current results are as follows:

Set default styles for bubbles and triangles

The core display is of course set to absolute positioning:

/* Bubble default style */ &::after {display: block; content: attr(tooltip); position: absolute; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding: 8px 15px; max-width: 200px; border-radius: 4px; Box-shadow: 0 10px 20px -5px rgba(0, 0, 0, 0.4); z-index: 100; @extend .tooltip-theme-dark; /* Inherit the default theme (white text on black) */} /* triangle default style */ &::before {display: block; content:' '; position: absolute; border: 5px solid transparent; z-index: 100; @extend .triangle-theme-dark; /* Inherit the default theme (black bottom) */}Copy the code

The current results are as follows:

Customize bubble and triangle theme colors

Define two themes:

$white: #fff;
$black: # 313131;/* bubble theme */. Tooltip-theme-dark {color:$white;
  background-color: $black;
}

.tooltip-theme-light {
  color: $black;
  background-color: $white;
  border: 1px solid $black; } /* triangle theme */. Triangle-theme-dark {border-top-color:$black;
}

.triangle-theme-light {
  border-top-color: $black; /* The same as dark */}Copy the code

Customize bubble and triangle positions (only one direction for example)

/ * bubble location * / / * -- -- * /. Tooltip - placement - top {bottom: calc + 10 px (100%); left: 50%; transform: translate(-50%, 0); } .tooltip-placement-top-right { bottom: calc(100% + 10px); left: 100%; transform: translate(-100%, 0) } .tooltip-placement-top-left { bottom: calc(100% + 10px); left: 0; Transform: translate(0, 0)} /* Triangle position */ /*---- on ----*/. Triangle -placement-top {bottom: calc(100% + 5px); left: 50%; transform: translate(-50%, 0); } .triangle-placement-top-left { bottom: calc(100% + 5px); left: 10px; } .triangle-placement-top-right { bottom: calc(100% + 5px); right: 10px; }Copy the code

Capture location, theme

This is the core code, matching the values on the tag with the property selector, and then setting different styles

Match bubble, triangle theme:

&[effect="light"] { &::after { @extend .tooltip-theme-light; } &::before { @extend .triangle-theme-light; }}Copy the code

Match bubble, triangle position, 12 positions:

@each $placement in top,top-right,top-left,
right,right-top,right-bottom,
bottom,bottom-right,bottom-left,
left,left-top,left-bottom {
  &[placement="# {$placement}"] {
    &::after {
      @extend .tooltip-placement-#{$placement};
    }

    &::before {
      @extend .triangle-placement-#{$placement};}}}Copy the code

Tags with no placement attribute/empty inherit top position by default:

&:not([placement]),
&[placement=""] { &::after { @extend .tooltip-placement-top; } &::before { @extend .triangle-placement-top; }}Copy the code

The current results are as follows:

Let’s make the text longer and add the default styles of bubbles and triangles to display: None.

Add a animation

Divided into four directions, up and down, left and right, four animations:

@keyframes anime-top { from { opacity: .5; bottom: 150%; } } @keyframes anime-bottom { from { opacity: .5; top: 150%; } } @keyframes anime-left { from { opacity: .5; right: 150%; } } @keyframes anime-right { from { opacity: .5; left: 150%; }}Copy the code

To determine which animation to execute, use [attr^=] to select, for example, upper left and upper right:

/* Set the animation */ @each$placement in top,
 right,
bottom,
left {
  &[placement^="# {$placement}"] {

    &::after,
    &::before {
      animation: anime-#{$placement} 300ms ease-out forwards;}}}Copy the code

The final effect is as follows:

IO /anon/pen/yR…

The last

If you think this article is good, please don’t forget to like and follow 😊