Hover and blur effect using Tailwind

I came across a nice interactive visual effect on the Gifmock website and thought it would be an interesting exercise to see how I could implement the same effect using Tailwind.

Two rows of grey logos, with the second row blurred but the Google logo is shown in full colour.

The first job was to take the existing HTML and strip back the current classes, so I just had the markup of the SVG logos. I changed the <div> containers to <a> links, so these logos could be focusable and clicked.

The first part of the Tailwind conversion was to set the correct layout. On small screens, the logos are wrapped within their space and organised evenly vertically and horizontally. The current CSS uses display: flex to achieve this and we can use Tailwind to do exactly the same;

<div class="flex flex-wrap justify-center max-w-7xl mx-auto">
    Logos…
</div>

Styling the logos

Instead of applying Tailwind classes to each individual link and SVG, I opted to use arbitrary variants. This means that more items can be added without any additional Tailwind markup. The logos need to be centred and have some spacing around them. I opted to use padding instead of the useful space between utilities, due to how the items wrap on smaller screens. The [&>a] is a child selector, meaning all the links directly inside the container.

<div class="… [&>a]:flex [&>a]:items-center [&>a]:px-5 [&>a]:py-4">
    Logos…
</div>

The SVG logos are full-colour, which is dictated by the fill on the <path> elements inside each SVG. The default state of these elements needed to be grey with the colour shown on highlight. I tried to set the fill property using fill-slate-900, but when hovering the SVG I was unable to reset the fill back to the initial defined in the markup. Therefore I had to negate the fill, so it only applied when not being hovered or focused.

[:not(&>a:hover_path,&>a:focus_path)]:fill-slate-900

A couple of the logos were aligned visually with the help of arbitrary margin values. I recreated these by using margin top class – mt-x – on the relevant SVGs.

Scaling the logos

Next, the logos become bigger when hovered. The original design makes the logos smaller initially, then zooms them to their original size. They also change from a low opacity to full opacity. These effects are applied directly to the SVG elements. To use CSS descendant selectors (which use spaces in the CSS declaration), Tailwind uses an underscore.

[&_svg]:scale-75 [&_svg]:opacity-30

When the links are hovered or focused, we want to scale the SVG back to the original size and opacity back to 100%. Here, when the child <a> has the hover/focus state, we select the descendant SVG element and apply the scale/opacity changes.

[&>a:hover_svg]:scale-100 [&>a:hover_svg]:opacity-100
[&>a:focus_svg]:scale-100 [&>a:focus_svg]:opacity-100

To make the animation smoother between these states, a transition effect is used. Tailwind supports transition properties and durations (as well as timing functions and delays). The original uses 400 milliseconds and transitions just the transforms, here I am applying the transition to all properties.

[&_svg]:transition-all [&_svg]:duration-400

Blurring the logos

The final puzzle piece was the blur effect. When the container is hovered but not when the link is hovered or focused then the SVG needs to be blurred. Tailwind supports applying blur filters so it was a case of finding the correct selector.

[&>a:not(:hover,:focus)_svg]:hover:blur

The logo HTML

The final HTML for the logos looks like this…

<div class="
	flex flex-wrap justify-center max-w-7xl mx-auto
	[&>a]:flex [&>a]:items-center [&>a]:px-5 [&>a]:py-4 [&>a]:outline-none
	[&_svg]:transition-all [&_svg]:duration-400
	[&_svg]:opacity-30 [&_svg]:scale-75
	[:not(&>a:hover_path,&>a:focus_path)]:fill-slate-900
	[&>a:hover_svg]:opacity-100 [&>a:hover_svg]:scale-100
	[&>a:focus_svg]:opacity-100 [&>a:focus_svg]:scale-100
	[&>a:not(:hover,:focus)_svg]:hover:blur">
	Logos…
</div>

Layout and Header

Finally, I added a heading which linked to the inspiration for the effect. I wrapped the heading and logos in another container, so it could be vertically and horizontally centred. Centring like this is extremely easy using flex and justify-center and space-y-x gives gaps between the title, logos and any other elements that might be added. I added some padding, an arbitrary value for the background colour (to match the original) and made the container fill the screen height.

<div class="flex flex-col justify-center space-y-6 p-8 bg-[#f1f3f5] min-h-screen">
	<h3 class="text-center text-3xl font-normal text-gray-700">
		Hover/Blur effect based on <a href="https://gifmock.com" class="
		underline underline-offset-4 outline-none
		hover:no-underline focus:no-underline
		hover:text-blue-500 focus:text-blue-500">Gifmock</a>.
	</h3>
	
	Logos HTML…
</div>

You can view the final template on Tailwind Play, where you can edit the HTML and experiment with the design on the fly.