I’ve got a banner that when hovered on displays an "underline" at the bottom of the container. Currently it’s achieved using ::after
and the functionality is perfect, but I don’t like having to be so specific with the bottom: -65px
, it feels a bit hacky and not truly responsive.
For example, if the banner was not exactly 150px, then the underline would be off.
Is there a way I can avoid using specific px values for bottom in this use case?
body {
margin: 0;
}
.banner {
height: 150px;
background-color: lightpink;
display: flex;
justify-content: center;
align-items: center;
}
ul {
display: flex;
align-items: center;
gap: 25px;
}
ul li {
list-style: none;
}
ul li a {
position: relative;
text-decoration: none;
}
ul li a::after {
position: absolute;
bottom: -65px;
left: 0;
right: 0;
width: 0%;
content: '';
color: transparent;
background: black;
height: 3px;
}
ul li a:hover::after,
ul li a:active::after {
transition: all 0.2s;
width: 100%;
}
<div class="banner">
<ul>
<li><a href="">Option 1</a></li>
<li><a href="">Option 1</a></li>
<li><a href="">Option 1</a></li>
</ul>
</div>
2
Answers
One possible approach would be to make the
a
elements take all the available height so you can specifybottom: 0;
on the pseudo element like this :Another approach could be to use CSS variables to specify the height of the header and adapt the positioning of the pseudo element accordingly.
In the following example, you can change the height of the banner by changing the value of
--banner-height: 150px;
and the positioning of the pseudo element will adapt withmargin-bottom: calc(var(--banner-height) / -2);
(note that y also changed the value ofbottom
to50%
).The whole
::after
isn’t nessecary.You can use the
border-bottom
declaration:As you can see, the results will differ. You can change the vertical position by editing
a
‘s height.This may be not what you’re looking for, as the underline won’t slide out, it will just "appear".