I came across a design tutorial on magic indicators from YouTube and created the following design: https://i.sstatic.net/IJjdCGWk.png
However, I am looking to achieve a smoother curve as a continuation of the circle when selected, instead of using elements with small border-radius like in the original solution. I'm struggling to make it perfectly match the border of the circle. The code snippet is provided below. I have indicated with arrows on the screenshot where I tried manual adjustments that didn't work well. I am seeking a CSS-only solution. https://i.sstatic.net/IYJ9UxoW.png
const indicator = document.querySelector("[data-indicator]")
document.addEventListener("click", e => {
let anchor
if (e.target.matches("a")) {
anchor = e.target
} else {
anchor = e.target.closest("a")
}
if (anchor != null) {
const allAnchors = [...document.querySelectorAll("a")]
const index = allAnchors.indexOf(anchor)
indicator.style.setProperty("--position", index)
document.querySelectorAll("a").forEach(elem => {
elem.classList.remove("active")
})
anchor.classList.add("active")
}
})
*, *::before, *::after {
box-sizing: border-box;
font-family: Arial, Helvetica, sans-serif;
}
body {
background-color: var(--background-color);
color: white;
}
:root {
--icon-size: 2rem;
--indicator-spacing: calc(var(--icon-size) / 8);
--border-radius: calc(var(--icon-size) / 4);
--nav-item-padding: calc(var(--icon-size) / 2);
--background-color: #333;
}
.navbar-container {
background-color: white;
border-radius: var(--border-radius);
width: max-content;
margin: 0 auto;
margin-top: 10rem;
padding: 0 calc(var(--nav-item-padding) * 1.5);
}
.list {
display: flex;
margin: 0;
padding: 0;
list-style: none;
}
.list a {
color: #333;
text-decoration: none;
display: flex;
flex-direction: column;
align-items: center;
padding: var(--nav-item-padding);
}
.list .text {
font-size: .8em;
opacity: 0;
pointer-events: none;
transition: 250ms ease-in-out;
position: absolute;
bottom: calc(.5 * var(--nav-item-padding));
transform: translateY(50%);
}
.list .icon {
position: relative;
transition: 250ms ease-in-out;
}
.list .icon svg {
fill: currentColor;
width: var(--icon-size);
height: var(--icon-size);
display: block;
}
.list .active .text {
pointer-events: all;
opacity: 1;
transform: translateY(0);
}
.list .active .icon {
transform: translateY(calc(-50% - var(--nav-item-padding)));
}
/* .list .active::before {
content: "";
box-sizing: content-box;
position: absolute;
width: var(--border-radius);
height: var(--border-radius);
background-color: white;
z-index: 1;
top: calc(-1 * var(--indicator-spacing));
left: calc(.2 * var(--indicator-spacing));
transform: translateX(-100%);
border-top-right-radius: 100%;
border-width: calc(var(--indicator-spacing));
border-color: var(--background-color);
border-style: solid;
border-bottom: none;
border-left: none;
}
.list .active::after {
...
}
...
.indicator {
position: absolute;
left: calc(var(--position) * (var(--icon-size) + var(--nav-item-padding) * 2));
transition: 250ms ease-in-out;
}
...
.corners::before {
...
}
LET'S KEEP THE HTML CONTENT UNCHANGED