
Lessons Learned - CSS Pseudo Elements
I have been working on a variety of link effects that use transitions on the ::before pseudo-element. The general approach is to have an absolutely positioned ::before element with a background transition into the link using translate
, scale
, skew
, and/or opacity
. For example:
1.link {
2 position: relative; /* need this for ::before absolute to work */
3 display: inline-block;
4 overflow: hidden;
5 &::before {
6 content: "";
7 position: absolute;
8 top: 0; bottom: 0; left: 0; right: 0;
9 background-color: LightSteelBlue;
10 transition: transform .3s ease;
11 /* base state */
12 transform: translateY(100%);
13 }
14 /* hover state */
15 &:hover {
16 &::before {
17 transform: translateY(0);
18 }
19 }
20}
If you try this, you will notice that we have a layering problem. The ::before (pseudo) element appears over the link. This seems counterintuitive to me. The name ::before
suggests that it comes before the link. But layering is a mystery, and I know how to solve the problem: give ::before
a negative z-index.
1.link {
2 ...
3 &::before {
4 ...
5 z-index: -1;
6 }
7 ...
8}
I am so brilliant. Now, my transformations work. You can see my brilliance in this pen.
Or was I "so brilliant"? The transformations no longer appear when I put these fancy links on parent elements with a background color. You can see this by changing the --pageBG
variable from transparent
to something like FloralWhite
in the pen.
I spent hours figuring out why adding a background would cause a problem. All the posts I read did not mention the issue, and StackOverflow offered no help. Finally, I stumbled on this MDN article on "Stacking Context" and it became clear that my understanding of layering (stacking) was elementary. In essence, z-index
is a relative value (relative within its stacking context). My knowledge was really lacking (and continues to be) where these stacking contexts exist. I highly recommend reading "Stacking Context" and be sure to look at the related to articles that go into more detail.
So, how does this help us with our fancy :hover
effect failing when we place the link on a parent with a background?
Long story short, we must create a new stacking context for the parent. From the MDN article, one way to create a new context is to set the parent's position to relative
and give the parent a z-index
.
Element with aposition
valueabsolute
orrelative
andz-index
value other thanauto
.
Another is to use the `isolation` css property...
Element with an isolation
value isolate
.
Here is the corrected Pen with the new stacking context applied to the parent of the links.
Here is the link hover effect that I was originally creating. Note: It is not working. You must add the stacking context to make it work with the background. I leave this update as a test of your understanding. :-)