skip to Main Content

i basically am trying to place the after and before pseudo elements behind anchor tag but they are still appearing on upfront , even though i have allocated them z-index

a{
    padding:1rem 1.5rem;
    background-color:whitesmoke;
    border-radius:12px;
    text-decoration:none;
    font-size:1.1rem;
    color:black;
    position:relative;
    z-index:2;
    user-select:none;
    cursor:pointer;
}
a:hover::after{
    content:'';
    position:absolute;
    height:50%;
    width:50%;
    bottom:2px;
    right:3px;
    box-shadow:5px 5px 40px 10px rgb(142, 224, 231);
    transition:all 0.5s;
    animation:shinny2 1s ease-in 1;
    animation-fill-mode:forwards;
    z-index: 0;
}
a:hover::before{
    content:'';
    position:absolute;
    z-index:0;
    height:50%;
    width:50%;
    top:2px;
    left:3px;
    box-shadow:-5px -5px 40px 10px rgb(142, 224, 231);
    animation:shinny1 1s ease-in 1;
    animation-fill-mode:forwards;
}
<a href="#">Foo</a>

2

Answers


  1. Your <a> tag has the z-index of 2, which is higher than the default value auto (which is 0 if it has a stacking context).

    When you assign its child pseudo elements to z-index: 0;, even they’re smaller than 2, but they’re not going to compare the z-index with its parent. (Otherwise you have to assign every of its ascendence with the same or higher z-index in order to show them)

    Unless you give them a negative z-index, then they’ll be shown behind the parent, because they’re compared with the global stacking context instead of local.

    a{
        padding:1rem 1.5rem;
        background-color:whitesmoke;
        border-radius:12px;
        text-decoration:none;
        font-size:1.1rem;
        color:black;
        position:relative;
        user-select:none;
        cursor:pointer;
    }
    a:hover::after{
        content:'';
        position:absolute;
        height:50%;
        width:50%;
        bottom:2px;
        right:3px;
        box-shadow:5px 5px 40px 10px rgb(142, 224, 231);
        transition:all 0.5s;
        animation:shinny2 1s ease-in 1;
        animation-fill-mode:forwards;
        z-index: -1;
    }
    a:hover::before{
        content:'';
        position:absolute;
        z-index:-1;
        height:50%;
        width:50%;
        top:2px;
        left:3px;
        box-shadow:-5px -5px 40px 10px rgb(142, 224, 231);
        animation:shinny1 1s ease-in 1;
        animation-fill-mode:forwards;
    }
    <a href="#">Foo</a>

    But using a negative z-index has a drawback, that it will be appeared behind every other elements but not only its parent, unless they have a even lower z-index (negative z-index hell).

    main {
      padding: 50px;
      background-color: gray;
    }
    
    a{
        padding:1rem 1.5rem;
        background-color:whitesmoke;
        border-radius:12px;
        text-decoration:none;
        font-size:1.1rem;
        color:black;
        position:relative;
        user-select:none;
        cursor:pointer;
    }
    a:hover::after{
        content:'';
        position:absolute;
        height:50%;
        width:50%;
        bottom:2px;
        right:3px;
        box-shadow:5px 5px 40px 10px rgb(142, 224, 231);
        transition:all 0.5s;
        animation:shinny2 1s ease-in 1;
        animation-fill-mode:forwards;
        z-index: -1;
    }
    a:hover::before{
        content:'';
        position:absolute;
        z-index:-1;
        height:50%;
        width:50%;
        top:2px;
        left:3px;
        box-shadow:-5px -5px 40px 10px rgb(142, 224, 231);
        animation:shinny1 1s ease-in 1;
        animation-fill-mode:forwards;
    }
    <main>
      <a href="#">Foo</a>  
    </main>

    If don’t want to mess around with z-index, a workaround is to utilize translateZ to put the pseudo elements behind its content, that will only be affected in the local 3d stacking context. So you don’t need to worry about the interations with other elements.

    a {
      /* make sure the 3d stack works */
      transform-style: preserve-3d;
      display: inline-block;
    }
    
    a::before, a::after {
      /* put the pseudo elements behind the content */
      transform: translateZ(-1px);
    }
    
    main {
      padding: 50px;
      background-color: gray;
    }
    
    a{
        padding:1rem 1.5rem;
        background-color:whitesmoke;
        border-radius:12px;
        text-decoration:none;
        font-size:1.1rem;
        color:black;
        position:relative;
        user-select:none;
        cursor:pointer;
        display: inline-block;
        transform-style: preserve-3d;
    }
    a:hover::after{
        content:'';
        position:absolute;
        height:50%;
        width:50%;
        bottom:2px;
        right:3px;
        box-shadow:5px 5px 40px 10px rgb(142, 224, 231);
        transition:all 0.5s;
        animation:shinny2 1s ease-in 1;
        animation-fill-mode:forwards;
        transform: translateZ(-1px);
    }
    a:hover::before{
        content:'';
        position:absolute;
        height:50%;
        width:50%;
        top:2px;
        left:3px;
        box-shadow:-5px -5px 40px 10px rgb(142, 224, 231);
        animation:shinny1 1s ease-in 1;
        animation-fill-mode:forwards;
        transform: translateZ(-1px);
    }
    <main>
      <a href="#">Foo</a>
    </main>
    Login or Signup to reply.
  2. Declaring z-index: -1 on the pseudo-elements does the job.

    It appears that the z-index of the pseudo-elements is relative to the anchor. Giving the anchor z-index: 0 keeps the stacking order of the elements while allowing the pseudo-elements to be underneath only the anchor.

    div {
      padding: 1em;
      background-color: aliceblue;
    }
    
    p {
      padding: 1.5em;
      background-color: ghostwhite;
    }
    
    a {
      position:relative;
      padding:1rem 1.5rem;
      font-size:1.1rem;
      text-decoration:none;
      background-color:whitesmoke;
      border-radius:12px;
      z-index: 0;
    }
    
    a:hover::after,
    a:hover::before {
      content:'';
      position:absolute;
      height:50%;
      width:50%;
      z-index: -1;
    }
    
    
    a:hover::after {
      bottom:2px;
      right:3px;
      box-shadow:5px 5px 40px 10px rgb(142, 224, 231);
    }
    
    a:hover::before {
      top:2px;
      left:3px;
      box-shadow:-5px -5px 40px 10px rgb(142, 224, 231);
    }
    <div>
      <p><a href="#">Foo</a></p>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search