I'm making a Navbar that can transform between desktop & mobile version based on the screen width.
Unlike as Bootstrap's Navbar that utilizes @media (min-width: ${minWidth}px)
for switching,
I am using a JavaScript for overflowing detection, by comparing $0.clientWidth
& $0.scrollWidth
.
The problem is, the paddingRight
doesn't substract the $0.clientWidth
, so the detection is inaccurate.
I want to get the actual client width without padding as shown by Chrome's page inspector.
As marked by the green rectangle on this illustration:
Note:
- I cannot apply a hack by adding
::after
for filling the right side, because the container is a grid, thus causing the ugly column gap. - I cannot apply marginRight to the menu because the margin will fill the gridArea.
Here the mockup of my Navbar.
Please focus on the .js file:
CodePudding user response:
If you are using list, i mean if your structure is like as
<ul>
<li>
<a href="#">
</a>
</li>
</ul>
Then give the padding
to the anchor tag, and then get the width of the li
tag, your problem will be resolve
CodePudding user response:
basically you want the actual width of the element without padding, you can achieve this by using javascript
<script>
function getWidth() {
var elemWidth =
document.getElementById("navbar").offsetWidth;
alert(elemWidth);
}
</script>
inshort the trick is offsetWidth
to get the elements inner-width.
CodePudding user response:
I updated your code please check
javascript
console.log('loaded')
const navbar = document.querySelector("#navbar");
const indicator = document.querySelector("#indicator");
const menu = document.querySelector('.menu');
new ResizeObserver(() => {
const overflowed = navbar.scrollWidth > navbar.clientWidth;
if (overflowed) {
indicator.classList.add('mobile');
indicator.classList.remove('desktop');
indicator.value = "overflowed => switch to mobile version";
menu.classList.add('mobile');
}
else {
indicator.classList.add('desktop');
indicator.classList.remove('mobile');
indicator.value = "not overflowed => desktop version";
menu.classList.remove('mobile');
}
})
.observe(navbar, { box: 'border-box' });
Css
body {
margin: 20px;
}
.navbar {
padding-inline: 80px;
padding-block: 10px;
background: #186EFB;
border: solid 3px darkblue;
min-height: 50px;
display: grid;
grid-template-columns: min-content 1fr;
grid-template-rows: 1fr;
grid-template-areas: "logo menu";
column-gap: 10px;
justify-items: center;
align-items: center;
}
.logo {
grid-area: logo;
display: inline-block;
background: red;
border: solid 3px darkred;
width: 30px;
height: 30px;
}
.menu {
grid-area: menu;
align-self: stretch;
justify-self: stretch;
display: block;
background: #14924C;
border: solid 3px darkgreen;
min-width: 300px;
height: 50px;
}
#indicator.desktop {
background: lightgreen;
}
#indicator.mobile {
background: pink;
}
.menu.mobile{
max-width: 300px;
min-width: auto;
}