I tried to make a border around an anchor/button but somehow the z-index doesn't work in the following code, even though I assigned a position to either of them. It works with a negative z-index to an extent (but then other pseudo-classes such as :hover etc. won't work --> see my last question), but can someone please explain why the ::before pseudo-element keeps on showing on top of the button and not underneath it?
Here is my Code:
.start-coding {
display: block;
font-size: 1.3rem;
color: white;
background-color: black;
padding: 0.4rem 1.8rem;
position: relative;
z-index: 5;
border-radius: 5px;
width: 100%;
}
.start-coding::before {
content: '';
background: linear-gradient(115deg, #4fcf70, #fad648, #a767e5, #12bcfe, #44ce7b);
border-radius: 5px;
position: absolute;
top: -3px;
left: -3px;
right: -3px;
bottom: -3px;
z-index: 1;
}
<a href="#" class="start-coding">Start Coding</a>
That is because you have positioned your pseudo-element absolutely in the <a>
element, and this causes it to be stacked on top of the text node, which has static positioning.
To solve this issue, simply wrap the inner text with <span>
and then add this rule:
.start-coding > span {
position: relative;
z-index: 2;
}
Even better: you don't even need to add z-indices to both ::before
and the nested <span>
, since they come in an order that ensures that, when they are placed in a stacking context, the <span>
will always be on top (since it comes after the ::before
element in the DOM tree). See example:
.start-coding {
display: block;
font-size: 1.3rem;
color: white;
background-color: black;
padding: 0.4rem 1.8rem;
position: relative;
z-index: 5;
border-radius: 5px;
width: 100%;
}
.start-coding::before {
content: '';
background: linear-gradient(115deg, #4fcf70, #fad648, #a767e5, #12bcfe, #44ce7b);
border-radius: 5px;
position: absolute;
top: -3px;
left: -3px;
right: -3px;
bottom: -3px;
}
.start-coding>span {
position: relative;
}
<a href="#" class="start-coding"><span>Start Coding</span></a>