Fancy Menu Hover Effects
Codrops is a great source of info. One of their articles is about creating cool hover effects for menus. The effects are cool but I’ve never found them easy to implement. And because of that difficulty they’re time consuming to implement so easy to not to bother with. This article is an attempt to get a better understanding of how these work.
Menu example
Here’s an example of one menu.
How?
There are a number of important principles that underscore these effects. They use some or all of the following:
- The
:hoverpseudo-selector obviously (so not much use for mobile) - The pseudo-elements
::beforeand::afterand styling these into shapes and lines or even other words. - Because
::beforeand::afteruse the defaultdisplay: inline;you need to change thisdisplay: inline-blockorposition: absoluteso thattransformand other CSS properties will work on them. You can also usegridorflexand they will behave as child elements (that can presumabley be re-ordered!). - A
transitionproperty because animations happen over time, even if it’s only two tenths of a second. - A transform property. These allow movement of an element that won’t affect nearby objects. If using more than one keep them together:
transform: scale(0.7) opacity: 0.1 translateX(150%); - Changing the
positionvalue toabsoluteorrelative - Using
opacityto fade effects in and out. - Using the
z-indexto stack the pseudo-elements. The parent can be set toisolation: isolateto keep the stacking context within itself, thus prevent the pseudo elements ending up behind it.
Optionally some effects may use:
- a data attribute on the anchor tag:
<a href="#" data-hover="menu 1">that can be used in the::beforeor::aftercontent value:content: attr(data-hover); - Some
<span>tags inside the anchor tags. - The property
pointer-eventshas a default ofautobut might need to be set tonone, particularly on pseudo-elements to stop them reacting to the cursor. This switches off things likecursor: pointeron links. backface-visibilityis used when a 3D rotation takes place. The default value isvisiblemeaning you’ll see text from the other side. You can set it tobackface-visibility: hiddenif you want to hide it.
Some things to watch out for
-
You often want to style
::beforeand::aftertogether. But you cannot use these pseudo elements with:is()and:where(). -
When you hover you are hovering over the anchor element NOT it’s pseudo elements which may not even be visible. Therefore watch your syntax: use
a:hover::beforeand NOTa::before:hover. -
Using
z-indexon pseudo elements is tricky.Firstly if the parent’s display is neither to
gridnorflexit won’t work unless thepositionvalue is set to something other than the default ofstatic, egrelative.Secondly using
postion: relativewith az-indexvalue creates a new stacking context. This means all z-index values are relative to this particular group or parent and child elements.Thirdly because although the pseudo-elements are inside their parent element they can end up behind out out of view. You may want something behind the text but still visible. So
a::beforeis insidea. To make this work set the pseudo-element (inside) to a negative value and the parent to a positive one. Setting parent’sz-indexfrom the default ofautosets a new stacking context for it’s chidren. Now they can’t go behind the parent.A better way is is to set
isolation: isolateon the parent instead of az-indexvalue. This means the parent’s layering position is not fixed. It is also more obvious what the intention is when we read the code. -
When setting the
position: absolutein the pseudo-elements don’t forget to setposition: relativein the parent, ie. in these cases the anchor tag.
Z-index rules
So after writing the above I thought I’d better write a brief synopsis of rules around the z-index.
- Only works on elements that have a position set (ie. not the default of
static). - When a stacking context is set the root element is at the back, then elements with a negative z-index, then elements with no z-index (default is 0?), then elements with a positive z-index.
- If two or more elements have the same z-index (or is unset) the order is determined by their position in the HTML document. Lower down in the doc appear above those lower down.