I made 2 buttons and a indicator to show which one is selected, but I don’t know how to center the indicator to the selected button vertically. The 2 buttons use flex: 1; for positioning. I’m sorry if my code is trash. I’m still learning how to code. I also want the indicator to slide to the other button smoothly.
let selectedHeaderButton = 1;
document.querySelector('.for-you-button').addEventListener('click', () => {
selectedHeaderButton = 1;
})
document.querySelector('.following-button').addEventListener('click', () => {
selectedHeaderButton = 2;
})
body {
height: 3000px;
margin-top: 100px;
font-family: Noto Sans, Arial;
}
.header {
position: relative;
text-align: center;
top: 0;
left: 0;
right: 0;
border-bottom: 1px solid rgb(239, 243, 244);
height: 106.5px;
}
.header-background {
background-color: rgb(255, 255, 255, 0.5);
top: 0;
left: 0;
right: 0;
height: 106.5px;
backdrop-filter: blur(4px);
position: fixed;
}
.nav-selected {
display: block;
font-weight: bold;
text-align: left;
margin-left: 15px;
font-size: 19px;
filter: none;
margin-top: 15px;
margin-left: 10px;
}
.header-buttons {
position: absolute;
height: 106.5px;
top: 0;
left: 0;
right: 0;
display: flex;
align-items: flex-end;
}
.for-you-button,
.following-button {
flex: 1;
border: none;
background-color: rgba(255, 255, 255, 0);
font-weight: 600;
font-size: 15px;
height: 53px;
transition: background-color 150ms;
text-align: center;
color: rgb(83, 100, 113);
}
.for-you-button:hover,
.following-button:hover {
background-color: rgba(200, 200, 200, 0.5);
}
.selected-button {
height: 4px;
width: 53px;
background-color: rgb(29, 155, 240);
position: absolute;
bottom: 0;
border-radius: 15px;
left: var(--x);
}
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
<header class="header-background">
<header class="header">
<div class="nav-selected">Home</div>
<div class="header-buttons">
<button class="for-you-button">For You</button>
<button class="following-button">Following</button>
</div>
<div class="selected-button"></div>
</header>
</header>
<main>
<div class="tweet-container">
<img>
<div>Minecraft <span>@Minecraft · Jul 12</span></div>
<div>
It's time for a new type of challenge! Show us your mob-making skills and build your pet in Blockbench. Don't forget to use the hashtag #FeatureMeMinecraft! Get started in our Creator Portal: https://minecraft.net/en-us/creator
</div>
</div>
</main>
2
Answers
We can exploit the fact that the buttons are equal width and take up the same width as the
.selected-button
‘s container. This means we can position the selected indicator relative to its position container and it will line up with the buttons.First let’s establish some bearings. We can apply:
To center
.selected-button
exactly in the horizontal center.left: 50%
places.selected-button
‘s left edge to the.header
‘s mid point.transform: translateX(-50%)
then moves the.selected-button
‘s left edge to the left by half its width, thereby aligning.selected-button
‘s mid point with.header
‘s mid point.With
left: 50%
being the middle between the two buttons, then we can deduce thatleft: 25%
andleft: 75%
will be the middle of the two buttons. We can thus apply the default selection of the left button in CSS:And then manipulate the
left
property when one clicks on either button:Lastly, to slide to the other button smoothly, we’ll add
transition
:All together:
Here is a bit more of an elegant solution in my opinion.
First, I updated and reduced your code a bit to be a bit more modern.
I.E. Get rid of a lot of the hardcoded pixels and let the padding and flex framework do the work and consolidate CSS to show you better practices. Generally speaking, there are not many reasons these days to be hardcoding pixel sizes, especially when working with flexbox or grid.
This approach simply listens for a click, finds the the currently selected button and removes the "selected" class, then adds the "selected" class to the button you clicked. It then adds a pseudo element to the selected button that will always be centered. This eliminates any need for math/margin fun and is also scalable.
Hope this helps!