首页 > 解决方案 > 动态居中工具提示

问题描述

我正在尝试使工具提示居中,但我希望当它溢出时它会根据位置向右或向左移动。

这是示例。我希望在这种情况下工具提示向右移动,但如果铃铛位于不会溢出的位置,则工具提示必须居中。

:root {
    --blue: hsl(190, 10%, 60%);
    --dark: hsl(0, 0%, 10%);
    --dark-light: hsl(0, 0%, 50%);
    --light: hsl(0, 0%, 100%);
}

body {
    margin: 0;
    font-family: sans-serif;
    height: 100vh;
    display: grid;
}

.main {
    max-height: 100%;
    margin: 10px;
    display: flex;
    border: 1px solid var(--dark-light);
}

.notifications {
  margin:10px;
}

.notifications::before{
  content: 'hover over bell';
  width: 100px;
  height: 100px;
}

.notifications-content {
    height: 25px;
    width: 25px;
    position: relative;
    display: flex;
    justify-content: center;
}

.notifications-content svg {
    height: 100%;
    width: 100%;
}

.notifications-content::after {
    content: attr(notifications-tooltip);
    visibility: hidden;
    opacity: 0;
    background-color: var(--dark);
    color: white;
    overflow: auto;
    padding: 5px;
    border-radius: 10px;
    position: absolute;
    top: 110%;
    transition: opacity 0.5s;
}

.notifications-content:hover::after {
    opacity: 1;
    visibility: visible;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Mastering Front End</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class='main'>
        <div class="notifications">
            <div class='notifications-content' notifications-tooltip='Here are your notifications'>
               <svg id="Layer_4" enable-background="new 0 0 24 24" height="512" viewBox="0 0 24 24" width="512" xmlns="http://www.w3.org/2000/svg"><g><path d="m21.379 16.913c-1.512-1.278-2.379-3.146-2.379-5.125v-2.788c0-3.519-2.614-6.432-6-6.92v-1.08c0-.553-.448-1-1-1s-1 .447-1 1v1.08c-3.387.488-6 3.401-6 6.92v2.788c0 1.979-.867 3.847-2.388 5.133-.389.333-.612.817-.612 1.329 0 .965.785 1.75 1.75 1.75h16.5c.965 0 1.75-.785 1.75-1.75 0-.512-.223-.996-.621-1.337z"/><path d="m12 24c1.811 0 3.326-1.291 3.674-3h-7.348c.348 1.709 1.863 3 3.674 3z"/></g></svg>
            </div>
        </div>
    </div>
</body>
</html>

标签: htmlcssstyling

解决方案


使用 Java 脚本,您可以使用变量来设置在伪元素中使用的单位。使用 javascript,您可以获得元素的位置并在数学上计算出位置,然后使用条件检查元素相对于窗口边缘的位置,以在 dom 中正确定位工具提示。document.documentElement

下面是一个基本示例,说明如何使用您的代码完成此操作。我在 Java Script 中添加了注释,希望能帮助您进一步了解正在发生的事情。

// set the root to the document.documentElement HTML element
const root = document.documentElement;
// get the .main element
const main = document.querySelector('.main');
// get the .notification-content element
const ntfctnsCntnt = document.querySelectorAll('.notifications-content');

// getBoundingClientRect() and computed styles
const mainRect = main.getBoundingClientRect()
const mainRight = mainRect.x + mainRect.width
const compStyleRoot = getComputedStyle(root);
const ttContWidth = compStyleRoot.getPropertyValue('--tt-cont-width');
const rootRect = root.getBoundingClientRect();

// run each nodeList through a loop
ntfctnsCntnt.forEach(el => {
  // event listener on hover (mouseover)
  el.addEventListener('mouseover', e => {
    // set the event targets boundingClientRect
    const elRect = e.target.getBoundingClientRect()
    // e.targets width
    const elWidth = elRect.width;
    // get width of tooltip before DOM changes it using root variable
    let ttcWidth = ttContWidth;
    // if the tooltips width is greater than the windows left "0" + parent left => "main" 
    // which will be padding and/or margin, + the bell elements left then we set the 
    // tooltip to the right of the "bell" element

    // "parseInt(ttContWidth.split('px')[0]) we are removing the px portion from the string
    // and parsing this string as an integer so it can be compared with another number
    if (parseInt(ttContWidth.split('px')[0]) > rootRect.left + mainRect.left + elRect.left) {
      // set the varibale for --ttp-left-pos (left: ) to window.left + main.left + e.target.left
      // which will be right of the element
      root.style.setProperty(`--ttp-left-pos`, rootRect.left + mainRect.left + elRect.left + 'px')
    } else {
    // else we set the tooltip to the left of the "bell" element
      root.style.setProperty(`--ttp-left-pos`, `-${parseInt(ttContWidth.split('px')[0]) + elWidth}px` )
    }
  })
})
:root {
  --blue: hsl(190, 10%, 60%);
  --dark: hsl(0, 0%, 10%, 0.8);
  --dark-light: hsl(0, 0%, 50%);
  --light: hsl(0, 0%, 100%);
  --ttp-left-pos:0;
  --ttp-top-pos:100%;
  --tt-cont-width:100px;
}

body {
  margin: 0;
  font-family: sans-serif;
  height: 100vh;
  overflow-x: hidden;
  display: grid;
}

.main {
  max-height: 100%;
  margin: 10px;
  display: flex;
  border: 1px solid var(--dark-light);
  display: flex;
  justify-content: space-between;
}

.notifications:nth-of-type(1) {
  margin: 10px;
}

.notifications::before {
  content: 'hover over bell';
  width: 100px;
  height: 100px;
}

.notifications-content {
  height: 25px;
  width: 25px;
  position: relative;
}

.notifications:nth-of-type(2) {
  margin-top: 10px; 
}


.notifications-content svg {
  height: 100%;
  width: 100%;
}

.notifications-content::after {
  content: attr(notifications-tooltip);
  visibility: hidden;
  opacity: 0;
  background-color: var(--dark);
  color: white;
  overflow: auto;
  padding: 5px;
  border-radius: 10px;
  position: absolute;
  top: var(--ttp-top-pos);
  left: var(--ttp-left-pos);
  transition: opacity 0.5s;
  width: var(--tt-cont-width);
}

.notifications-content:hover::after {
  opacity: 1;
  visibility: visible;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Mastering Front End</title>
  
</head>

<body>
  <div class='main'>
    <div class="notifications">
      <div class='notifications-content' notifications-tooltip='Here are your notifications'>
        <svg id="Layer_4" enable-background="new 0 0 24 24" height="512" viewBox="0 0 24 24" width="512" xmlns="http://www.w3.org/2000/svg"><g><path d="m21.379 16.913c-1.512-1.278-2.379-3.146-2.379-5.125v-2.788c0-3.519-2.614-6.432-6-6.92v-1.08c0-.553-.448-1-1-1s-1 .447-1 1v1.08c-3.387.488-6 3.401-6 6.92v2.788c0 1.979-.867 3.847-2.388 5.133-.389.333-.612.817-.612 1.329 0 .965.785 1.75 1.75 1.75h16.5c.965 0 1.75-.785 1.75-1.75 0-.512-.223-.996-.621-1.337z"/><path d="m12 24c1.811 0 3.326-1.291 3.674-3h-7.348c.348 1.709 1.863 3 3.674 3z"/></g></svg>
      </div>
    </div>
    <div class="notifications">
      <div class='notifications-content' notifications-tooltip='Here are your notifications'>
        <svg id="Layer_5" enable-background="new 0 0 24 24" height="512" viewBox="0 0 24 24" width="512" xmlns="http://www.w3.org/2000/svg"><g><path d="m21.379 16.913c-1.512-1.278-2.379-3.146-2.379-5.125v-2.788c0-3.519-2.614-6.432-6-6.92v-1.08c0-.553-.448-1-1-1s-1 .447-1 1v1.08c-3.387.488-6 3.401-6 6.92v2.788c0 1.979-.867 3.847-2.388 5.133-.389.333-.612.817-.612 1.329 0 .965.785 1.75 1.75 1.75h16.5c.965 0 1.75-.785 1.75-1.75 0-.512-.223-.996-.621-1.337z"/><path d="m12 24c1.811 0 3.326-1.291 3.674-3h-7.348c.348 1.709 1.863 3 3.674 3z"/></g></svg>
      </div>
    </div>
  </div>
</body>

</html>


推荐阅读