skip to Main Content

I’m having trouble displaying tooltips to a vertical navigation list.

Here’s an example of my problem: https://codepen.io/achillebourgault/pen/ZEVVbGe?editors=1100

Basically, I have a parent div .leftnav-wrapper on which you can scroll up and down to unroll its content.
Each item is represented with a .listitem div and when you hover a tooltip is displayed. However, this tooltip is cut off, as it cannot exceed the width of the parent.

How can I solve this problem?

I first tried to have a element display: inline-flex;
by displaying .leftnav-wrapper as the first element and .content as the second, but I still have the same problem.
I then tried putting in relative position and .leftnav-wrapper in fixed position, but I still have the same problem.

<main>
  <div class="leftnav-wrapper">
    <div class="leftnav">
      <div class="listitem">
        <button>A</button>
        <div class="listitem-name">
          Example Item Name
        </div>
      </div>
    <div class="listitem">
        <button>A</button>
        <div class="listitem-name">
          Example Item Name
        </div>
      </div>
      <div class="listitem">
        <button>A</button>
        <div class="listitem-name">
          Example Item Name
        </div>
      </div>
      <div class="listitem">
        <button>A</button>
        <div class="listitem-name">
          Example Item Name
        </div>
      </div>
      <div class="listitem">
        <button>A</button>
        <div class="listitem-name">
          Example Item Name
        </div>
      </div>
      <div class="listitem">
        <button>A</button>
        <div class="listitem-name">
          Example Item Name
        </div>
      </div>
      <div class="listitem">
        <button>A</button>
        <div class="listitem-name">
          Example Item Name
        </div>
      </div>
      <div class="listitem">
        <button>A</button>
        <div class="listitem-name">
          Example Item Name
        </div>
      </div>
      <div class="listitem">
        <button>A</button>
        <div class="listitem-name">
          Example Item Name
        </div>
      </div>
      
      <div class="listitem">
        <button>A</button>
        <div class="listitem-name">
          Example Item Name
        </div>
      </div>
      
      <div class="listitem">
        <button>A</button>
        <div class="listitem-name">
          Example Item Name
        </div>
      </div>
      
      <div class="listitem">
        <button>A</button>
        <div class="listitem-name">
          Example Item Name
        </div>
      </div>
  </div>
 </div>
  <div class="content">
    Content
  </div>
</main>
* {
  margin: 0;
  padding: 0;
}

main {
  height: 100vh;
  width: 100%;
  overflow: hidden;
}

.leftnav-wrapper {
    width: 68px;
    max-height: 100vh;
    overflow-y: auto;
    overflow-x: hidden;
    position: fixed;
    z-index: 999;
}

.leftnav-wrapper::-webkit-scrollbar {
    width: 0;
    background: transparent;
}

.leftnav-wrapper::-webkit-scrollbar-thumb {
    background: transparent;
}

.leftnav-wrapper::-webkit-scrollbar-track {
    background: transparent;
}

.leftnav {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.listitem {
  background: #cecece;
  height: 52px;
  width: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.listitem-name {
  visibility: hidden;
  opacity: 0;
  position: absolute;
  left: 52px;
  transition; all 0.3s;
  background: green;
  width: 100px;
  overflow: visible;
  z-index: 999;
}

.listitem:hover .listitem-name {
  visibility: visible;
  opacity: 1;
  transition; all 0.3s;
}

.content {
  padding-left: 68px;
  background: black;
  width: 100%;
  height: 100vh;
  color: white;
}

This is the code I was working on before creating a codepen to isolate the problem:

import React from "react";

import styles from './LeftNavigation.module.css';

import {ServerListExample} from "../../assets/examples/ServerListExample";

export default function LeftNavigation() {
    return (
        <div className={styles.leftNavigation}>
            <div className={styles.listItem + " " + styles.privateMessages}>
                <div className={styles.listItemIcon + " " + styles.privateMessagesActive}>
                    <img src={"/images/discord-logo.png"} alt="Private Messages"/>
                    <div className={styles.listItemIconName}>Private Messages</div>
                </div>
            </div>
            <div className={styles.listItemSep}></div>
            <div className={styles.serversList}>
                {
                    ServerListExample.map((server, index) => {
                        return server.type === 'server' ? (
                            <div className={styles.listItem} key={index}>
                                <div className={styles.listItemIcon}>
                                    <img src={server?.avatar} alt={server?.name}/>
                                    <div className={styles.listItemIconName}>{server?.name}</div>
                                </div>
                            </div>
                        ) : (
                            <div className={styles.listItemGroup} key={index}>
                                <div className={styles.listItemGroupTitle}>
                                    <svg aria-hidden="true" role="img" width="24" height="24" viewBox="0 0 24 24" style={{color: 'rgb(88, 101, 242)'}}><path fill="currentColor" d="M20 7H12L10.553 5.106C10.214 4.428 9.521 4 8.764 4H3C2.447 4 2 4.447 2 5V19C2 20.104 2.895 21 4 21H20C21.104 21 22 20.104 22 19V9C22 7.896 21.104 7 20 7Z"></path></svg>
                                    <div className={styles.listItemGroupTitleName}>{server?.name}</div>
                                </div>
                                {server.childList.map((child, index) => {
                                    return (
                                        <div className={styles.listItem} key={index}>
                                            <div className={styles.listItemIcon}>
                                                <img src={child?.avatar} alt={child?.name}/>
                                                <div className={styles.listItemIconName}>{child?.name}</div>
                                            </div>
                                        </div>
                                    )
                                })}
                            </div>
                        )
                    })
                }
            </div>
        </div>
    )
}
/* LeftNavigation.module.css */

.leftNavigation {
    background: transparent;
    height: 100%;
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 8px;
    width: var(--left-navigation-width);
    user-select: none;
    align-items: center;
    z-index: 999;
    max-height: calc(100% - 16px);
    overflow-y: auto;
    position: relative;
}

.leftNavigation::-webkit-scrollbar {
    width: 0;
    background: transparent;
}

.leftNavigation::-webkit-scrollbar-thumb {
    background: transparent;
}

.leftNavigation::-webkit-scrollbar-track {
    background: transparent;
}

.listItem {
    display: flex;
    align-items: center;
    justify-content: center;
}

.listItemIcon {
    width: 50px;
    height: 50px;
    display: flex;
    justify-content: center;
    align-items: center;
    position: relative;
    border-radius: 25px;
    transition: all 0.3s;
    align-items: stretch;
    cursor: pointer;
}

.privateMessages .listItemIcon {
    align-items: center;
}

.listItemIcon .listItemIconName {
    position: absolute;
    top: 50%;
    left: 40px;
    transform: translateY(-50%);
    background: var(--black-100);
    color: #cecece;
    padding: 8px;
    border-radius: 8px;
    font-weight: bold;
    opacity: 0;
    transition: opacity 0.3s;
    display: none;
    z-index: 9999;
}

.listItemIcon:hover .listItemIconName {
    display: block;
    opacity: 1;
    transition: opacity 0.3s;
    position: absolute;
}


.listItemIcon:hover,
.listItemIcon:hover > img {
    border-radius: 16px;
    transition: all 0.3s;
}

.listItemIcon > img {
    border-radius: 50%;
    transition: all 0.3s;
    height: 48px;
    width: 48px;
}

.privateMessages img {
    height: 26px !important;
    width: 26px !important;
    object-fit: contain;
}

.listItemSep {
    margin: 0 auto 6px;
    width: 66%;
    border-bottom: solid var(--grey-200) 2px;
}

.privateMessagesActive {
    background: #5764f0;
}

.listItemGroup {
    display: flex;
    flex-direction: column;
    gap: 12px;
    width: fit-content;
    place-self: center;
    background: var(--grey-300);
    border-radius: 50px;
}

.listItemGroup .listItem:last-child img {
    margin-top: 2px;
}

.listItemGroupTitle {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 44px;
}

.listItemGroupTitle svg {
    height: 24px;
    width: 24px;
    fill: var(--grey-000);
    transition: all 0.3s;
}

.listItemGroupTitle .listItemGroupTitleName {
    display: none;
    opacity: 0;
    transition: opacity 0.3s;
    position: fixed;
    z-index: 1000;
}

.listItemGroupTitle:hover .listItemGroupTitleName {
    display: block;
    opacity: 1;
    transition: opacity 0.3s;
}

.serversList {
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: 100%;
    margin-top: -6px;
}

3

Answers


  1. Chosen as BEST ANSWER

    Thank you! It actually corrected my codepen problem. However, I tried to integrate the solution into my project and I don't understand what I'm doing wrong

    App.js

    // src/App.js
    import React from 'react';
    import TitleBar from "./components/TitleBar/TitleBar";
    
    import LeftNavigation from "./components/LeftNavigation/LeftNavigation";
    import LeftNavigationExtended from "./components/LeftNavigationExtended/LeftNavigationExtended";
    
    import {useState} from "react";
    import './assets/css/index.css';
    
    function App() {
        const [user, setUser] = useState({
            name: 'JohnDoe74',
            avatar: 'https://media-cldnry.s-nbcnews.com/image/upload/t_nbcnews-fp-1200-630,f_auto,q_auto:best/rockcms/2022-01/210602-doge-meme-nft-mb-1715-8afb7e.jpg',
            activity: 'online',
            microMuted: false,
            soundMuted: false,
        });
    
      return (
          <div className="parent">
            <TitleBar />
    
            <main>
                <div className="leftNavWrapper">
                    <LeftNavigation />
                </div>
              <div className="content">
                  <LeftNavigationExtended user={user} />
              </div>
            </main>
          </div>
      );
    }
    
    export default App;
    

    index.css

    .parent {
        height: 100%;
        width: 100%;
    }
    
    .parent main {
        display: flex;
        /*height: calc(100vh - var(--title-bar-height));*/
    }
    
    
    
    .private-messages {
        /*width: 100%;*/
        /*height: 100%;*/
        /*display: flex;*/
        /*flex-direction: column;*/
        /*gap: 6px;*/
        /*padding: 8px;*/
        /*overflow-y: auto;*/
    }
    
    .content {
        /*border-top-left-radius: 8px;*/
        /*width: calc(100vw -var(--left-navigation-width));*/
        /*height: calc(100vh - var(--title-bar-height));*/
        /*background: var(--black-300);*/
        width: 100%;
        height: 100vh;
        color: white;
    }
    
    
    .leftNavWrapper {
        width: var(--left-navigation-width);
    }
    
    .leftNavWrapper::-webkit-scrollbar {
        width: 0;
        background: transparent;
    }
    
    .leftNavWrapper::-webkit-scrollbar-thumb {
        background: transparent;
    }
    
    .leftNavWrapper::-webkit-scrollbar-track {
        background: transparent;
    }
    

    LeftNavigation.js

    import React from "react";
    
    import styles from './LeftNavigation.module.css';
    
    import {ServerListExample} from "../../assets/examples/ServerListExample";
    
    export default function LeftNavigation() {
        return (
            <div className={styles.leftNavigation}>
                <div className={styles.listItem + " " + styles.privateMessages}>
                    <div className={styles.listItemIcon + " " + styles.privateMessagesActive}>
                        <img src={"/images/discord-logo.png"} alt="Private Messages"/>
                        <div className={styles.listItemIconName}>Private Messages</div>
                    </div>
                </div>
                <div className={styles.listItemSep}></div>
                <div className={styles.serversList}>
                    {
                        ServerListExample.map((server, index) => {
                            return server.type === 'server' ? (
                                <div className={styles.listItem} key={index}>
                                    <div className={styles.listItemIcon}>
                                        <img src={server?.avatar} alt={server?.name}/>
                                        <div className={styles.listItemIconName}>{server?.name}</div>
                                    </div>
                                </div>
                            ) : (
                                <div className={styles.listItemGroup} key={index}>
                                    <div className={styles.listItemGroupTitle}>
                                        <svg aria-hidden="true" role="img" width="24" height="24" viewBox="0 0 24 24" style={{color: 'rgb(88, 101, 242)'}}><path fill="currentColor" d="M20 7H12L10.553 5.106C10.214 4.428 9.521 4 8.764 4H3C2.447 4 2 4.447 2 5V19C2 20.104 2.895 21 4 21H20C21.104 21 22 20.104 22 19V9C22 7.896 21.104 7 20 7Z"></path></svg>
                                        <div className={styles.listItemGroupTitleName}>{server?.name}</div>
                                    </div>
                                    {server.childList.map((child, index) => {
                                        return (
                                            <div className={styles.listItem} key={index}>
                                                <div className={styles.listItemIcon}>
                                                    <img src={child?.avatar} alt={child?.name}/>
                                                    <div className={styles.listItemIconName}>{child?.name}</div>
                                                </div>
                                            </div>
                                        )
                                    })}
                                </div>
                            )
                        })
                    }
                </div>
            </div>
        )
    }
    
    /* LeftNavigation.module.css */
    
    .leftNavigation {
        background: transparent;
        height: 100%;
        display: flex;
        flex-direction: column;
        gap: 12px;
        padding: 8px;
        width: var(--left-navigation-width);
        user-select: none;
        align-items: center;
        z-index: 999;
        max-height: calc(100% - 16px);
        overflow-y: auto;
        position: relative;
    }
    
    .leftNavigation::-webkit-scrollbar {
        width: 0;
        background: transparent;
    }
    
    .leftNavigation::-webkit-scrollbar-thumb {
        background: transparent;
    }
    
    .leftNavigation::-webkit-scrollbar-track {
        background: transparent;
    }
    
    .listItem {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .listItemIcon {
        width: 50px;
        height: 50px;
        display: flex;
        justify-content: center;
        align-items: center;
        position: relative;
        border-radius: 25px;
        transition: all 0.3s;
        align-items: stretch;
        cursor: pointer;
    }
    
    .privateMessages .listItemIcon {
        align-items: center;
    }
    
    .listItemIcon .listItemIconName {
        position: absolute;
        top: 50%;
        left: 40px; /* Ajustez la position horizontale selon vos besoins */
        transform: translateY(-50%);
        background: var(--black-100);
        color: #cecece;
        padding: 8px;
        border-radius: 8px;
        font-weight: bold;
        opacity: 0;
        transition: opacity 0.3s;
        display: none;
        z-index: 9999;
    }
    
    .listItemIcon:hover .listItemIconName {
        display: block;
        opacity: 1;
        transition: opacity 0.3s;
        position: absolute;
    }
    
    
    .listItemIcon:hover,
    .listItemIcon:hover > img {
        border-radius: 16px;
        transition: all 0.3s;
    }
    
    .listItemIcon > img {
        border-radius: 50%;
        transition: all 0.3s;
        height: 48px;
        width: 48px;
    }
    
    .privateMessages img {
        height: 26px !important;
        width: 26px !important;
        object-fit: contain;
    }
    
    .listItemSep {
        margin: 0 auto 6px;
        width: 66%;
        border-bottom: solid var(--grey-200) 2px;
    }
    
    .privateMessagesActive {
        background: #5764f0;
    }
    
    .listItemGroup {
        display: flex;
        flex-direction: column;
        gap: 12px;
        width: fit-content;
        place-self: center;
        background: var(--grey-300);
        border-radius: 50px;
    }
    
    .listItemGroup .listItem:last-child img {
        margin-top: 2px;
    }
    
    .listItemGroupTitle {
        position: relative;
        display: flex;
        align-items: center;
        justify-content: center;
        height: 44px;
    }
    
    .listItemGroupTitle svg {
        height: 24px;
        width: 24px;
        fill: var(--grey-000);
        transition: all 0.3s;
    }
    
    .listItemGroupTitle .listItemGroupTitleName {
        display: none;
        opacity: 0;
        transition: opacity 0.3s;
        position: fixed;
        z-index: 1000;
    }
    
    .listItemGroupTitle:hover .listItemGroupTitleName {
        display: block;
        opacity: 1;
        transition: opacity 0.3s;
    }
    
    .serversList {
        display: flex;
        flex-direction: column;
        gap: 8px;
        width: 100%;
        margin-top: -6px;
    }
    

  2. Welcome to Stackoverflow!

    If you replace the CSS of the main by this :

    main {
      display: flex;
      background: black
    }
    

    and you replace the CSS of .leftnav-wrapper the by this :

    .leftnav-wrapper {
        width: 68px;
    }
    

    I think it will work as you had expected!

    Login or Signup to reply.
  3. Could you please share a Codesandbox of your app?

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search