'Ho to Create a Horizontally Scrollable and Responsive Navbar Using React-Bootstrap
Code:
return(
<Navbar collapseOnSelect bg="dark" variant="dark" >
<Navbar.Brand href="#home">React-Bootstrap</Navbar.Brand>
<Navbar.Toggle aria-controls="responsive-navbar-nav" />
<Nav className="me-auto">
<Nav.Link href="#features">Features</Nav.Link>
<Nav.Link href="#pricing">Pricing</Nav.Link>
<Nav.Link href="#features">Features</Nav.Link>
<Nav.Link href="#pricing">Pricing</Nav.Link>
<Nav.Link href="#features">Features</Nav.Link>
<Nav.Link href="#pricing">Pricing</Nav.Link>
<Nav.Link href="#features">Features</Nav.Link>
<Nav.Link href="#pricing">Pricing</Nav.Link>
<Nav.Link href="#features">Features</Nav.Link>
<Nav.Link href="#pricing">Pricing</Nav.Link>
<NavDropdown title="Dropdown" id="collasible-nav-dropdown">
<NavDropdown.Item href="#action/3.1">Action</NavDropdown.Item>
<NavDropdown.Item href="#action/3.2">Another action</NavDropdown.Item>
<NavDropdown.Item href="#action/3.3">Something</NavDropdown.Item>
<NavDropdown.Divider />
<NavDropdown.Item href="#action/3.4">Separated link</NavDropdown.Item>
</NavDropdown>
</Nav>
<Nav>
<Nav.Link href="#deets">More deets</Nav.Link>
<Nav.Link eventKey={2} href="#memes">
Dank memes
</Nav.Link>
</Nav>
</Navbar>
)
As you can see in the screenshot, items are cut off on the right.
Question 1: How can I fit (show all the items) the navbar within the screen size (by scaling the size up or down depending on the device size) without collapsing and without adding line breaks (no multiple lines)?
Question 2: The issue with resizing is the text would become too small to read if the nav items are too many and the device is very small. Option two: How can I make it so that the navbar can be scrolled through horizontally (with a button on the left and another button on the right)?
This is how the current scrolling behaviour looks like:
See the issues highlighted:

Solution 1:[1]
Here you go:
Basically using Navbar from react-bootstrap with horizontally scrollable is a bad idea. I implemented the same successfully but the risk of horizontally scrollable feature made the dropdowns (if you have) pop behind the division so it was not visible on the page.
Its known as overflow issue. That means you can't have overflow-x: scroll and overflow-y: visible at the same time on the same division. Here is the code that could help you
import { Dropdown } from "react-bootstrap";
const renderNavigationTabs = () => {
<Dropdown alignRight key={id} navbar={true} id="page-navigation-drop-down-align-right"
className="pnt-navigation-navitem small-margin-item">
<Dropdown.Toggle id="page-navigation-drop-down-button" className={ "pnt-navigation-navlink " +
(item.children.find((element)=> element.link === history.location.pathname) ? "pnt-navigation-navlink-active" :
"pnt-navigation-navlink-deactive")
}
>
<span className="header-user-name">{item.title}</span>
<CaretDownFill />
</Dropdown.Toggle>
<Dropdown.Menu popperConfig={{ strategy: "fixed" }} id="header-menu-fixed">
{item.children.map((ele, index) => {
return (
<Dropdown.Item key={index} className="tsad-dropdown-item" onClick={()=> {
changeToNewLink(ele.link);
}}
>
{ele.title}
</Dropdown.Item>
);
})}
</Dropdown.Menu>
</Dropdown>
}
<div className="page-navigation-layout">
<button className="page-button-navigation left" onClick={(e)=> scrollLeft(e)}>
<<
</button>
<div id="scrollbar-page-navigation" className={"pnt-navbar" + (props.sideNavToggle
? " page-navigation-active" : "" )}>
<div className="mr-auto pnt-navigation">
{renderNavigationTabs()}
</div>
</div>
<button className="page-button-navigation right" onClick={(e)=> scrollRight(e)}>
>>
</button>
</div>
Styling:
$tabs-navbar-margin: calc(100vw / 15);
$links-margin: calc(100vw / 48);
$small-link-margin: calc(100vw / 288);
.page-navigation-layout {
width: stretch;
width: -webkit-fill-available; /* Mozilla-based browsers will ignore this. */
width: -moz-available; /* WebKit-based browsers will ignore this. */
display: flex;
align-items: flex-end;
justify-content: space-between;
border-bottom: 3px solid rgba(146, 153, 156, 0.05);
margin-bottom: 20px;
.pnt-navbar {
// margin: 30px $tabs-navbar-margin 20px $tabs-navbar-margin;
margin: 30px 20px 0 20px;
padding: 0;
width: calc(100vw - 204px);
max-width: initial;
transition: 0.5s ease;
overflow-x: scroll;
overflow-y: visible;
scroll-behavior: smooth;
scrollbar-color: #9b9b9b #eceef2;
scrollbar-width: none;
.pnt-navigation {
display: flex;
flex-direction: row;
justify-content: space-between;
.pnt-navigation-navitem {
margin-right: $links-margin;
margin-left: $links-margin;
white-space: nowrap;
.pnt-navigation-navlink {
font-size: 1.125em;
font-weight: 500;
padding: 8px 0px 15px 0px;
}
.pnt-navigation-navlink-deactive {
opacity: 0.6;
border: none;
color: var(--color);
}
.pnt-navigation-navlink-active {
opacity: 1;
border: none;
border-bottom: 3px solid var(--primary-color);
color: var(--color);
}
&:first-child {
margin-left: 0;
}
&:last-child {
margin-right: 0;
}
}
.small-margin-item {
margin-right: $small-link-margin;
margin-left: $small-link-margin;
}
.show.dropdown {
border-radius: 5px 5px 0 0;
background-color: var(--reports-page-background);
}
}
&::-webkit-scrollbar {
height: 0px;
}
&::-webkit-scrollbar-track {
height: 0px;
background-color: #eceef2;
border-radius: 180px;
}
&::-webkit-scrollbar-thumb {
height: 0px;
background-color: #9b9b9b;
border-radius: 180px;
}
}
.page-navigation-active {
width: calc(100vw - 494px);
}
.page-button-navigation {
margin-bottom: 21px;
min-height: 22px;
min-width: 22px;
max-width: 22px;
max-height: 22px;
border-radius: 5px;
border: none;
padding: 0;
background-color: var(--menu-item-highlight-color);
display: flex;
justify-content: center;
align-items: center;
svg {
height: 18px;
width: 14px;
color: var(--color);
}
}
.left {
margin-left: calc(100vw / 24);
}
.right {
margin-right: calc(100vw / 24);
}
}
#page-navigation-drop-down-align-right {
.btn-primary,
.btn-primary.dropdown-toggle,
#tsad-dropdown-basic:active,
#tsad-dropdown-basic:focus {
background-color: transparent;
color: var(--color);
box-shadow: none;
display: flex;
margin: auto;
align-items: center;
border-radius: 0;
font-size: 1.125em;
font-weight: 500;
padding: 15px 20px 15px 20px;
line-height: 22px;
svg {
margin-left: 10px;
}
}
.btn-primary::after {
display: none;
}
.dropdown-item.active,
.dropdown-item:active,
.dropdown-item:hover,
.dropdown-item:focus {
background-color: var(--menu-item-highlight-color);
color: var(--color);
}
}
#header-menu-fixed {
// position: fixed;
padding: 20px 0px;
a {
padding: 10px 30px;
opacity: 0.8;
color: var(--color);
font-family: Montserrat;
font-size: 1em;
line-height: 20px;
}
}
@media screen and (max-width: 1280px) {
.page-navigation-layout {
.page-navigation-active {
width: calc(100vw - 204px);
}
}
}
@media screen and (max-width: 540px) {
.page-navigation-layout {
.pnt-navbar {
width: calc(100vw - 84px - 100vw / 12);
.pnt-navigation {
.pnt-navigation-navitem {
.pnt-navigation-navlink {
font-size: 1em;
}
}
}
}
.left {
margin-left: calc(100vw / 24);
}
.right {
margin-right: calc(100vw / 24);
}
.page-navigation-active {
width: calc(100vw - 84px - 100vw / 12);
}
}
}
.navbar-nav {
flex: 1;
justify-content: space-around;
}
So basically its all about overflow-x and Dropdown from react-bootstrap provides popperConfig which works like a charm: https://react-bootstrap.github.io/components/dropdowns/#dropdown-menu-props
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Harry |

