Search code examples
cssangularbootstrap-5ng-bootstrap

Change overflow-visible for overflow-auto if the size of the element is bigger than the viewport


I have an Angular component that opens another component as an offcanvas:

  openTop() {
    this.offcanvasService.open(AdvancedSearchComponent, {
      position: 'top',
      backdropClass: 'bg-dark',
      panelClass: 'h-25 bg-danger text-bg-danger flex-column',
      keyboard: true,
    });
  }

Then in that offcanvas component I have something like this:

<nav class="navbar navbar-expand-lg navbar-dark bg-danger">
  <div class="navbar-toggler border-0 ps-2 ps-sm-3 py-2 py-lg-0">
    <a class="navbar-brand" href="#"
      ><img src="assets/..."
    /></a>
  </div>
  <button
    class="navbar-toggler mx-2 mb-2"
    type="button"
    data-bs-toggle="collapse"
    data-bs-target="#navbarSearch"
    aria-controls="navbarSearch"
    aria-expanded="false"
    aria-label="Toggle navigation"
  >
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse flex-grow-1" id="navbarSearch">
    <form
      class="overflow-auto flex-grow-1"
      (ngSubmit)="searchTask()"
      [formGroup]="searchForm"
    >
      <div class="offcanvas-header pe-0 pt-0 pb-1 align-items-start">
...

And some of the css that might be relevant is:

:host {
  height: 100%;
  display: flex;
  flex-direction: column;
}
form {
  scrollbar-gutter: stable;
}

If I add overflow-auto to the <nav> element, the height of the top offcanvas is 25vh and there's a scroll bar when the content doesn't fit vertically.

If I add overflow-visible to the top <nav> element, or no overflow class at all, then the offcanvas panel expands when the content doesn't fit vertically. The offcanvas panel itself has some buttons with data-bs-toggle="collapse" that can make the content grow and overflow the screen. The problem is that if the content overflows the screen there's no scrollbar, as I have overflow-visible. What I need is to have overflow-visible when the offcanvas panel occupies 25%-100% of the viewport, but overflow-auto when the content is larger than 100% of the viewport.

What I want to achieve is to have the top offcanvas panel adjust in size to the content, but when the content overflows the size of the screen to have a scrollbar to be able to see the entire content.

Things I have tried:

  • Some SO questions/answers have suggested that the problem might be having body {overflow: hidden}. This is indeed the case in my app, at least when I inspect the elements on my offcanvas. However, removing that style from the body has only added a scrollbar that scrolls the "background" content, not the offcanvas content.

  • I have tried adding additional <div> elements with different classes.

  • I have tried using max-height and height on css, or the correspoding bootstrap classes on my element, but I couldn't achieve what I wanted.

  • Some solutions suggest using padding in order to solve this type of problem, but I didn't understand how.


Solution

  • I have found the solution. For some reason, for some reason, .h-auto was giving me a panel height of 100vh, regardless of whether collapsible elements were expanded or not. The trick was to have .overflow-visible when I open the offcanvas panel, and in this way the height of the panel adjusted to the content.

      openTop() {
        this.offcanvasService.open(AdvancedSearchComponent, {
          position: 'top',
          backdropClass: 'bg-dark',
          panelClass: 'h-25 bg-danger text-bg-danger d-flex flex-column overflow-visible',
    
          keyboard: true,
        });
      }
    

    Then, in order to add a scrollbar I realized that what I was missing was setting a height the child element:

        <form
          class="overflow-auto flex-grow-1 form-height"
          (ngSubmit)="searchTask()"
          [formGroup]="searchForm"
        >
    

    css:

    .form-height {
      max-height: 95vh;
    }
    

    That did the trick I was looking for: the offcanvas has a minimum height of 25vh, it expands up to about 100vh, and if the content expands beyond the viewport, it adds a scrollbar. For some reason, .overflow-auto.h-auto didn't adjust the height to the content, and it showed an offcanvas panel that filled 100% of the screen, even if all the elements were collapsed.