Key Takeaways
- The :hover pseudo-class is a useful tool for providing visual feedback to users when mousing over links and buttons. It can be styled in various ways, such as changing the color, size, or orientation of an element. However, it is not consistently reliable on touch devices, and should not be used to hide key information.
- Other pseudo-classes can be utilized to style different link states, such as :visited for links in a user’s browser history, :active for a link being clicked on, and :focus for a link currently in keyboard focus. These can be grouped together in a reset stylesheet to set defaults for a project.
- The :hover pseudo-class can also be used to create dropdown menus in a site’s main navigation. This involves toggling the display property of sub-menus when hovering over top-level menu items. To make this interaction work well on touch devices, JavaScript can be used to convert hover events into click events.
This screencast is a part of our AtoZ CSS Series. You can find other entries to the series here.
Transcript
Hover is a pseudo class and can be used to style state.
The hover state is active when a user’s mouse enters the bounding box of an element and is inactive when the user’s mouse leaves it.
In this episode, we’ll look at the :hover
pseudo-class on text links and cover some of the other link pseudo classes as well. We’ll also look at some of the downsides of hover and some workarounds for non-mouse users. Finally we’ll create a CSS dropdown menu triggered by hover
and enhanced with jQuery for touch devices.
Links
Probably the most common use of :hover
is to provide visual feedback to users when mousing over links and buttons.
The hover state of a link can be styled in CSS as follows:
a:hover {color: red;}
The colon next to the a
signifies a pseudo class. We’ll look at a number of them in this video and throughout the rest of the series – and you can check out the :enabled
and :disabled
pseudo classes in “Episode 5: ID Selector
“.
In this example, just the color is being styled but any properties can be changed, overwritten, or canceled out. You could increase the font-size and rotate the link by 180 degrees if you wanted to – but don’t do that.
There are other pseudo classes that are useful for styling different link states too.
There’s a:visited
for styling links that the user has in their browser history. There’s also a:active
for styling a link that is currently being clicked on. Finally, there’s a:focus
for a link that currently has keyboard focus – ie. the user has used the tab
key to jump through the clickable items on a page like links and form inputs.
I like to group this set of four link states together as part of a reset stylesheet that will set sensible defaults for an entire project.
a {color: blue;}
a:hover {color: lightblue;}
a:visited {color: darkblue;}
a:focus {outline: 1px dotted grey;}
a:active {color: lightblue;}
The Downside
Hover states can be applied to any element – not just links – which makes them very versatile. But on touch devices, there’s no mouse to initiate the hover.
Hover styles sometimes get applied if a user taps very lightly on a link or button but this is not reliable and not consistent across platforms and devices. It can often be very confusing, and our job is to improve user experience, not make it worse!
In the case of touch devices, avoid key information being hidden behind hover interactions. If this can’t be done, it is possible to swap out hovers for clicks using JavaScript.
Some users aren’t able to use a mouse and we can improve the experience for them by always applying :focus
and :active
styles whenever we use :hover
. We can comma separate these in our CSS as follows:
a:hover,
a:focus,
a:active {
/* styles */
}
If you use a CSS pre-processor like Sass, you could create a mixin that would output these three comma separated pseudos for you without having to write them out all the time.
@mixin hover-focus-active() {
&:hover,
&:focus,
&:active { @content }
}
/* usage */
a {
/*styles*/
@include hover-focus-active {
/* styles */
}
}
Now your state based styles will show during keyboard interactions on elements that can be focused or made active.
CSS Dropdown Menu
We’ve seen a basic use of :hover
to give some visual feedback when interacting with links and buttons. Another common design pattern on the web is dropdown menus in a site’s main navigation.
We can use the hover interaction to show and hide a sub-menu by using more complex CSS selectors. To make this interaction behave nicely on touch devices, a small amount of JavaScript is required to convert hover events into click events – but we’ll take a look at that later.
The trick is to toggle the display
property of the sub menus when hovering over the top-level menu items. As :hover
is a CSS selector, it can be combined with other selectors in a chain to create more complex behaviour. For more info on the display
property, check out “Episode 4: Display
“.
In this example, I have a horizontal unordered list of links, each with a sub-menu positioned beneath them. The sub menus are another unordered list but with the list items stacked on top of each other.
This CSS, sets up this initial layout. The colour and font properties have been moved into my page-styles.css
file, to keep the working area clean.
.menu > li {
position: relative;
display: inline-block;
}
.menu .sub-menu {
position: absolute;
top: 100%;
left: 0;
}
The sub-menus can be hidden with display:none
and then set to display:block
when a menu item is being hovered over.
.menu li:hover .sub-menu {
display: block;
}
This will show all sub-menus but we can tweak this selector to limit the showing and hide to individual sub-menus by using the >
child selector. For more info on this and other combinator selectors, check out the previous episode on the general sibling selector.
.menu li:hover > .sub-menu {
display: block;
}
If you prefer less of a sudden snapping on or off of the sub menus, you could combine opacity
with transition
for more of a fade in, fade out effect. I’ll leave that as an exercise for you to play around with – make a Codepen and shoot me a tweet; I’d love to check out what you come up with.
To make this drop down menu play nice on touch devices, we can add in a bit of JavaScript. This jQuery snippet will activate the dropdown menus on click instead of hover; clicking a second time will allow any link in the top-level menu to be navigated to unless it’s an empty link.
if ('ontouchstart' in document.documentElement) {
$('.menu > li').has('.sub-menu').on('click', 'a', function(e) {
var $menuItem = $(this);
var target = $menuItem.attr('href');
if (!target || target === '#') {
return false;
}
if ($menuItem.is('.js-active')) {
return true;
}
e.preventDefault();
$menuItem.addClass('js-active').siblings().removeClass('js-active');
$('.sub-menu').hide();
$menuItem.find('.sub-menu').show();
});
}
A working example of this menu including the jQuery for touch devices can be found on Codepen.
Watch out for our Quick Tip article coming soon!Frequently Asked Questions (FAQs) about CSS Hover Pseudo Class
What is the difference between :hover, :focus, and :active pseudo-classes in CSS?
The :hover, :focus, and :active are all pseudo-classes in CSS that apply to different user interactions. The :hover pseudo-class is triggered when a user places their cursor over an element without activating it. The :focus pseudo-class applies when an element has received focus, typically through the user clicking on an input element or navigating to it using the keyboard. The :active pseudo-class is applied as soon as the user activates an element, such as by clicking on a link or button.
How can I use the :hover pseudo-class for different elements?
The :hover pseudo-class can be used with any HTML element, not just links. It can be used to change the appearance of buttons, form fields, images, and other elements when the user hovers over them. For example, you could change the background color of a button when the user hovers over it by using the following CSS:button:hover {
background-color: blue;
}
Can I use multiple pseudo-classes together?
Yes, you can chain multiple pseudo-classes together to create more specific selectors. For example, you could use the :hover and :focus pseudo-classes together to change the appearance of a link when it is hovered over or has focus:a:hover, a:focus {
color: red;
}
How does the :hover pseudo-class work with touch devices?
On touch devices, there is no concept of hovering, as there is no cursor. However, some touch devices will trigger the :hover pseudo-class when the user touches an element. This can lead to unexpected behavior if you’re not careful, so it’s important to consider touch devices when designing your hover effects.
Can I use the :hover pseudo-class with CSS animations?
Yes, you can use the :hover pseudo-class to trigger CSS animations. This can be used to create interesting effects when the user hovers over an element. For example, you could use the :hover pseudo-class to animate the color of a link:a {
color: blue;
transition: color 0.5s;
}
a:hover {
color: red;
}
In this example, the color of the link will smoothly transition from blue to red when the user hovers over it.
Front-end dev and teacher at The General Assembly London. A to Z CSS Screencaster, Founder of sapling.digital and Co-founder of The Food Rush.