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.
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.