skip to Main Content

How to truncate dynamic text(with variable width) inside a nav-link or nav-text in a bootstrap navbar?

P.S.: With explicit width, this code just works fine, ex.: <a class="nav-link disabled text-truncate" style="max-width: 150px;"> but the width is unknown.

The expected behavior, is truncate text on desktop and mobile viewports, no matter which viewport size.

Codepen

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">

<nav class="navbar navbar-expand-lg bg-body-tertiary">
  <div class="container-fluid">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
        <li class="nav-item">
          <a class="nav-link active" aria-current="page" href="#">Home</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#">Link</a>
        </li>
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
            Dropdown
          </a>
          <ul class="dropdown-menu">
            <li><a class="dropdown-item" href="#">Action</a></li>
            <li><a class="dropdown-item" href="#">Another action</a></li>
            <li>
              <hr class="dropdown-divider">
            </li>
            <li><a class="dropdown-item" href="#">Something else here</a></li>
          </ul>
        </li>
        <li class="nav-item">
          <a class="nav-link disabled text-truncate">long long long long long long long long long long long long long long long long long long long long long long long long long long long text</a>
        </li>
      </ul>
      <div class="d-flex" role="search">
        <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
        <button class="btn btn-outline-success" type="submit">Search</button>
      </div>
    </div>
  </div>
</nav>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>

I’ve tried @isherwood suggestions, but without success:

First:

.flex-parent,
.flex-parent-parent,
.flex-parent-parent-parent {
  display: flex;
  padding: 10px;
  border: solid;
  min-width: 100px;
}

.flex-parent {
  min-width: 0;
}

.long-and-truncated {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">

<nav class="navbar navbar-expand-lg bg-body-tertiary">
  <div class="container-fluid">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
        <li class="nav-item">
          <a class="nav-link active" aria-current="page" href="#">Home</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#">Link</a>
        </li>
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
            Dropdown
          </a>
          <ul class="dropdown-menu">
            <li><a class="dropdown-item" href="#">Action</a></li>
            <li><a class="dropdown-item" href="#">Another action</a></li>
            <li>
              <hr class="dropdown-divider">
            </li>
            <li><a class="dropdown-item" href="#">Something else here</a></li>
          </ul>
        </li>
        <li class="nav-item">
          <div class="flex-parent-parent-parent">
            <div class="flex-parent-parent">
              <div class="flex-parent">
                <div class="flex-child long-and-truncated">
                  1. This is a loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong string that is OK to truncate please and thank you
                </div>
              </div>
            </div>
          </div>

        </li>
      </ul>
      <div class="d-flex" role="search">
        <button class="btn btn-outline-success">Search</button>
      </div>
    </div>
  </div>
</nav>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>

Second:

.wrapper {
  display: flex;
  /*   width: 200px; */
  align-content: stretch;
  padding: 5px;
  min-width: 0;
  border: 1px solid
}

.wrapper .child2 {
  flex-grow: 1;
  overflow: hidden;
}

.flex {
  display: flex;
  min-width: 0;
}

.el {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.child1 {
  background: red;
}

.child2 {
  background: lightblue;
}

.child3 {
  background: green;
}

.wrapper>* {
  padding: 5px;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />

<nav class="navbar navbar-expand-lg bg-body-tertiary">
  <div class="container-fluid">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
  <span class="navbar-toggler-icon"></span>
</button>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
        <li class="nav-item">
          <a class="nav-link active" aria-current="page" href="#">Home</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#">Link</a>
        </li>
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
        Dropdown
      </a>
          <ul class="dropdown-menu">
            <li><a class="dropdown-item" href="#">Action</a></li>
            <li><a class="dropdown-item" href="#">Another action</a></li>
            <li>
              <hr class="dropdown-divider">
            </li>
            <li><a class="dropdown-item" href="#">Something else here</a></li>
          </ul>
        </li>
        <li class="nav-item">

          <div class="wrapper">
            <div class="child1">child1</div>
            <div class="child2">
              <div class="flex">
                <div class="el">long long long long long long long long long long long long long long long long long long long long text</div>
                <div>a</div>
              </div>
            </div>
            <div class="child3">child3</div>
          </div>

        </li>
      </ul>
      <div class="d-flex" role="search">
        <button class="btn btn-outline-success">Search</button>
      </div>
    </div>
  </div>
</nav>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>

Both(apparently) need a explicit width to truncate text.
My text come from API, and have no length restriction, that cause in a layout mess.

2

Answers


  1. Here’s your solution,

    Notes:

    • The commented css at the bottom was my first attempt to achieve the result and was more concise it achieved it, but as bootstrap uses flex-wrap on smaller devices rather than changing flex direction, the overflow-x:hidden prevented the dropdown to show, so commented css prevent dropdown navbar item from showing its content.

    • Then I modified the solution by coming with some tweaks for the css behavior by specifying some small widths for items that I know would overflow and adding some media query rules and the solution is working fine, check it.

    • Finally, I made the text that overflows scrollabe when hovering over it while hiding its scrollbars, so truncated text can be scrolled through and seen entirely rather than being totally inaccessible.

    .container-fluid-custom{
      width: 100vw;
    }
    
    .navbar-nav-custom {
      flex: 1;
      width: 0;
    }
    
    .nav-item-custom::-webkit-scrollbar {
      display: none;
    }
    .nav-item-custom {
      flex: 1;
      width: 0;
    }
    
    .nav-item-custom:hover{
      margin-right: 1rem;
      overflow: auto;
      -ms-overflow-style: none;  /* IE and Edge */
      scrollbar-width: none; /*  Firefox */
    }
    
    .nav-item-custom:hover .text-truncate{
      overflow: visible !important;
    }
    
    @media (max-width: 992px) {
    
      .show {
        width: 100%;
      }
     
      .navbar-nav {
        width: 100%;
        overflow-x: hidden;
      }
    
      .nav-item-custom {
        width: 100%;
      }
    
    }
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
    
    <nav class="navbar navbar-expand-lg bg-body-tertiary">
      <div class="container-fluid container-fluid-custom">
        <a class="navbar-brand" href="#">Navbar</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse navbar-collapse-custom" id="navbarSupportedContent">
          <ul class="navbar-nav navbar-nav-custom me-auto mb-2 mb-lg-0">
            <li class="nav-item">
              <a class="nav-link active" aria-current="page" href="#">Home</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Link</a>
            </li>
            <li class="nav-item dropdown">
              <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                Dropdown
              </a>
              <ul class="dropdown-menu">
                <li><a class="dropdown-item" href="#">Action</a></li>
                <li><a class="dropdown-item" href="#">Another action</a></li>
                <li>
                  <hr class="dropdown-divider">
                </li>
                <li><a class="dropdown-item" href="#">Something else here</a></li>
              </ul>
            </li>
            <li class="nav-item nav-item-custom">
              <a class="nav-link disabled text-truncate">long long long long long long long long long long long long long long long long long long long long long long long long long long long text</a>
            </li>
          </ul>
          <div class="d-flex" role="search">
            <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
            <button class="btn btn-outline-success" type="submit">Search</button>
          </div>
        </div>
      </div>
    </nav>
    
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>

    commented CSS of first trial, where dropdown item got hidden by overflow-x: hidden. This isn’t the solution, but for reference, if you want to try it and maybe come out with another solution.

    /* .navbar-collapse-custom{
      overflow-x: hidden;
    }
    
    .navbar-nav-custom{
       white-space: nowrap;
       overflow-x: hidden;
       text-overflow: ellipsis;
      
    }
    
    .nav-item-custom{
      overflow-x:hidden;
    } */
    

    An advice:

    • with your progression on front end development, you would see custom made libraries such as bootstrap hinders your freedom of implementation, that’s why in some cases you should create your own UI components from scratch fully customized to your own purpose.
    Login or Signup to reply.
  2. I don’t get your actual problem to be honest, you keep changing the problem scope by adding more nested elements or more flex elements. Here is a fix for your First and Second examples.

    .expect-long {
      min-width: 0;
    }
    .expect-long *:has(.long) {
      min-width: 0;
      display: flex;
    }
    .long {
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    .nav-item:has(.long) {
      display: flex;
      align-items: center;
    }
    .navbar-collapse [role="search"] {
      flex-shrink: 0;
    }
    
    
    .wrapper {
      display: flex;
    }
    .wrapper>* {
      padding: 5px 15px;
    }
    .child1 {
      background: red;
    }
    .child2 {
      background: lightblue;
    }
    .child3 {
      background: green;
    }
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
    
        <nav class="navbar navbar-expand-lg bg-body-tertiary">
      <div class="container-fluid">
        <a class="navbar-brand" href="#">Navbar</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse expect-long" id="navbarSupportedContent">
          <ul class="navbar-nav me-auto mb-2 mb-lg-0">
            <li class="nav-item">
              <a class="nav-link active" aria-current="page" href="#">Home</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Link</a>
            </li>
            <li class="nav-item dropdown">
              <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                Dropdown
              </a>
              <ul class="dropdown-menu">
                <li><a class="dropdown-item" href="#">Action</a></li>
                <li><a class="dropdown-item" href="#">Another action</a></li>
                <li><hr class="dropdown-divider"></li>
                <li><a class="dropdown-item" href="#">Something else here</a></li>
              </ul>
            </li>
            <li class="nav-item">
              <div class="wrapper">
                <div class="child1">child1</div>
                <div class="child2">
                  <div>
                    <div>
                        <div>
                            <div class="long">long long long long long long long long long long long long long long long long long long long long text</div>
                        </div>
                    </div>
                    <div>a</div>
                  </div>
                </div>
                <div class="child3">child3</div>
              </div>
            </li>
          </ul>
          <div class="d-flex" role="search">
            <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
            <button class="btn btn-outline-success" type="submit" onclick="changeItem()">Change</button>
          </div>
        </div>
      </div>
    </nav>
    
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search