Skip to content

Update nav link & pill items height#42146

Merged
mdo merged 4 commits intotwbs:v6-devfrom
pricop:patch-6
Mar 12, 2026
Merged

Update nav link & pill items height#42146
mdo merged 4 commits intotwbs:v6-devfrom
pricop:patch-6

Conversation

@pricop
Copy link

@pricop pricop commented Mar 11, 2026

Currently, link and nav-pills items height sit at 36px (because they don't have any borders), while tab, and underline sit at 38px, which perfectly matches the height of input and button components.

This PR adds an invisible border for the link and nav-pills items, so that all 4 nav variants share the exact same height, regardless of which is used, which makes it suitable to be used with other components, such as input or buttons without having discrepancy when it comes to elements height.

v6 feedback discussion thread at: https://github.com/orgs/twbs/discussions/42145 - where I've included an example with detailed description.

Currently, `link` and `nav-pills` items height sit at `36px` (because they don't have any borders), while `tab`, and `underline` sit at `38px`, which perfectly matches the height of  `input` and `button` components.

This PR adds an invisible border for the `link` and `nav-pills` items, so that all 4 `nav` variants share the exact same height, regardless of which is used, which makes it suitable to be used with other components, such as `input` or `buttons` for example, as described in this discussion: https://github.com/orgs/twbs/discussions/42145 without having discrepancy when it comes to elements height.
@pricop pricop requested a review from a team as a code owner March 11, 2026 00:51
@pricop
Copy link
Author

pricop commented Mar 11, 2026

As a side note, the --nav-tabs-border-radius CSS var in the $nav-tabs-tokens tokens map doesn't seem to be used anywhere (or anymore). If this is a left over, it should be removed. You can either remove it or I can send a PR or a patch to this PR to address that as well.

@pricop
Copy link
Author

pricop commented Mar 11, 2026

Second side note...

I've noticed that:

--nav-link-padding-x: .75rem,
--nav-link-padding-y: .375rem,

in the $nav-tabs-tokens tokens map have the exact same padding as button / input components.

Not sure what's your take on this but I feel like defaulting them to the root --btn-input-padding-x and --btn-input-padding-x would be great, as they'll follow the global design language, while still being customizable on a per-component scope, should one want that, because in the end, they do feel like buttons - and they are used as buttons in certain cases, even the Documentation suggests that.

I can also do a PR / patch with this change as well:

    --nav-link-padding-x: var(--btn-input-padding-x),
    --nav-link-padding-y: var(--btn-input-padding-y)

Just wanted to ask first if that's something you'd consider.

Copy link
Member

@mdo mdo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PRs, these have been super helpful!

scss/_nav.scss Outdated
Comment on lines 213 to 215
border-inline: 0;
border-block-start: 0;
border-block-end: var(--nav-underline-border-width) solid transparent;
Copy link
Member

@mdo mdo Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shorten this down a bit maybe?

Suggested change
border-inline: 0;
border-block-start: 0;
border-block-end: var(--nav-underline-border-width) solid transparent;
border-width: 0;
border-block-end: var(--nav-underline-border-width) solid transparent;

Copy link
Author

@pricop pricop Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't work, as border-width is resetting the physical border.

So when we set border-block-end with no specific width value, then the browser will set a logical border, that will default to 3px, as that's what the browsers default to for border-block, as a result, the whole element renders at at 39px (1px extra).

So we can either keep the first (initial commit) version, or we completely reset the border using border property instead, and set the border-block-end as before, which includes a defined width for it.

border: 0;
border-block-end: var(--nav-underline-border-width) solid transparent;

I've mocked up a codepen with the initial commit, the 2 line alternative, and your example to show the possible solutions, and why border-width doesn't work in this case: https://codepen.io/editor/pricop/pen/019cde14-71b3-7cc1-be57-d67ead2c0268

Let me know which route to go 👍.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohhh right right. Ya use border: 0 for now—it's a logical reset for the modifier. Good eyes!

scss/_nav.scss Outdated
Comment on lines 60 to 61
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must've missed this earlier, mind including here?

Suggested change
--nav-pills-link-active-color: var(--primary-contrast),
--nav-pills-link-active-bg: var(--primary-bg),

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done 👍.

Copy link
Author

@pricop pricop Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've unresolved this temporarily. Please don't push this code just yet, I want to have a deeper look at this.

The --nav-pills-link-active-color applies correctly to nav pills, and it looks fine there, however it doesn't work on navbar pills, which makes use of color: var(--navbar-active-color); instead, due to precedence or specificity.

When active, the text should have been white here instead.

image

Will update this thread shortly.

Copy link
Author

@pricop pricop Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mdo Since v6 will introduces soft button variants, in my opinion this would be the perfect candidate to use the soft variant colors from buttons both for nav and navbar

What's your take on something like this instead. We could either go with the Primary, or Secondary route.

Primary soft
image

Secondary soft
image


What do you think?

L.E.: This is already achieved with nav links, my bad.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that the nav-links already achieve this, my bad 😅.

So I guess pills do make sense to be a solid in that case. I went ahead and commited everything.

Kindly please review whenever you have time.

Will submit a separate PR for the navbar with fixed paddings, and fixed text color for the pills. 👍

Copy link
Author

@pricop pricop Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad @mdo, I've edited my comment. This is already achieved using the nav-link items.

So pills do make sense to be primary color here. And, in-fact, I've seen cases where this is actually used.

E.g:

image

So I've included your commit, and fixed the border to be a one-liner.

One last thing if you don't mind, the --nav-tabs-border-radius doesn't seem to be used anymore, is this safe to remove? If yes, I can do this change as well, and we can close this PR.

I'll do a separate PR for the navbar, because I believe there's several ways we can improve it. 👍

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mdo It can already be achieved simply by using nav link instead of navbar-nav on the navbar component.

image

It looks 🔥, but I wonder if this was done on purpose? Previously, in BS4 and BS5 nav links would be just... links, with not background effect on hover/active, they only had text color effects.

If this was on purpose, the pills are kinda redundant.

If it wasn't on purpose, then perhaps we could make pills what nav links are today, and nav-links what they used to be in the past (just styled links).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it was on purpose because it seemed a little weak of us to not offer a default component that functioned properly. We did the same with .btn having a functional set of styles across all states. It introduces some redundancy for sure, I thought about removing pills, but I think stylistically we can have default nav use subtle theme variants and pills use higher contrast contrast/bg.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense, but then you should consider removing pills beacuse the high contrast can be easily achieved now in two different ways (this is where BS + CSS vars really shine).

I was able to achieve 1:1 to what pills component is doing simply by adding style="--bs-nav-link-active-bg: var(--bs-primary-bg); --bs-nav-link-active-color: var(--bs-primary-contrast);" to the nav-link.

Here's the result:

image

In fact, I've seen this mentioned multiple times in Bootstrap docs, where it suggests customizing the color by using an inline style.

Furthermore, if someone wants this to be the default state for all navigation menus, then they simply customize the component.

Lastly, but not least, by removing the pills, we lower CSS footprint (rather important since BS is now at 270kb+ from 140kb+ in v4).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And, additionally, this issue will disappear: #42146 (comment) too, as there's no more CSS precedence taking place.

The Docs for nav and navbar would require slight adjustment (we'll have to remove the pills references).

This is definitely for a separate PR. Think about it, and if you're okay with such a change, you can either do it, or I can send a PR.

Comment on lines 19 to 20
--nav-link-padding-x: .75rem,
--nav-link-padding-y: .375rem,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these values, as you mentioned, I could see us using the --btn-input-* root tokens, but the name needs an update at that point. I can address that later.

Suggested change
--nav-link-padding-x: var(--btn-input-padding-x),
--nav-link-padding-y: var(--btn-input-padding-y),

Copy link
Author

@pricop pricop Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, perhaps something like --interactive-element-padding-x would be an idea since button, input, pagination, nav are elements you interact with.

Just something to think about. Would be nice being able to customize the nav button spacing alongside with the rest of the buttons, without having to deep dive into component specific CSS.

Either way, BS6 is set to be amazing. Saas maps feel so much nicer after using them for a while, compared to the sass varibles 😍.

pricop and others added 2 commits March 11, 2026 21:11
Co-authored-by: Mark Otto <markdotto@gmail.com>
Shortened the code for borders by using `border` attribute.

Also applied the correct background for pill shaped items.
@pricop
Copy link
Author

pricop commented Mar 12, 2026

I've discovered a small side effect, you might want to look at this.

While browsing between local/dev docs demo, I've noticed that after I've added the invisible border, the sidebar text from the menu is offset by 1px compared to the category title. This is obviously because of the newly added border.

Before adding 1px border width (notice no pixel gap between the red line and "Q" letter)

image

After adding 1px border width (notice the 1px gap between the red line and "Q" letter)

image

To make the docs look like before, border-0 will have to be applied on nav-link element.

I questioned if this was the right change to do, but I've detailed more in my next comment.

@pricop
Copy link
Author

pricop commented Mar 12, 2026

Bootstrap is already doing this with buttons and badges, so that further reinforces that we should have an invisible border for nav links, and pills.

I believe width & height should be the same across all styles, similarly to how button and badge work, where we have a styled button with a visibile border, and a subtle button that has no visible border, but the subtle one still matches the same height & width, which makes complete sense.

Additionally, when using nav (not navbar-nav) on a navbar container, it will also make it so that it matches when used with other inline elements, such as an input form, a button, etc., which is that's another plus for consistency.

Instances such as this will look perfect if we keep the invisible border:

image

So the only downside to this would be the one I've presented: when used in a sidebar menu, like the official docs, alongside category titles, there's going to be a one px difference when trying to match the paddings. This can easily be adjusted by setting the border-start-0, or border-0 on nav-link, but it is something to consider before you approve/decline this.

Your call 🙃.

@mdo
Copy link
Member

mdo commented Mar 12, 2026

Sidebar is totally fine, throw .border-0 on the whole thing in the sidebar. I like the condensed sidebar look that we have going so want to keep that spacing intact if possible. Rest of this all sounds good!

Removed the invisible border so that the sidebar remains as condensed as it was before.
@pricop
Copy link
Author

pricop commented Mar 12, 2026

I've added border-0 to the nav-link so the sidebar is now 1:1 to how it was before. This should be ready.

For the pills topic, if you want me to remove them for the reasons mentioned at: #42146 (comment) feel free to let me know, and I can open a separate PR for those as well.

@mdo
Copy link
Member

mdo commented Mar 12, 2026

For the pills topic, if you want me to remove them for the reasons mentioned at: #42146 (comment) feel free to let me know, and I can open a separate PR for those as well.

Let's do it in another PR once I merge this :). Thanks!

@mdo mdo merged commit ea3c78a into twbs:v6-dev Mar 12, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Inbox

Development

Successfully merging this pull request may close these issues.

3 participants