JFXtras RadialMenu for NetBeans RCP (Part 2)

this article is part 2 of a tutorial that will walk through adapting an open source javafx radialmenu (  http://jfxtras.org/  ) to replace the netbeans platform system menu.  it will build upon both previous tutorials and  part 1  that demonstrate complete replacements for the default netbeans swing components using javafx.  code examples will feature netbeans platform, javafx and css.

part 1  of the article walks through some of the code upgrades necessary for the task.  as of this article’s writing the open-source jfxtras radialmenu needed a few upgrades to act as a system menu replacement for a netbeans platform rcp.  part 2 will show the specific algorithm and code to then utilize the upgraded radialmenu as described.  when complete you should be able to produce a slick radial system menu like this:

Newer Things to Know About Good Ol’ HTML Lists

HTML lists are boring. They don’t do much, so we don’t really think about them despite how widely used they are. And we’re still able to do the same things we’ve always done to customize them, like removing markers, reversing order, and making custom counters.

There are, however, a few “newer” things — including dangers — to know when using lists. The dangers are mostly minor, but way more common than you might think. We’ll get to those, plus some new stuff we can do with lists, and even new ways to approach old solutions.

To clarify, these are the HTML elements we’re talking about:

  • Ordered lists <ol>
  • Unordered lists <ul>
  • Description lists <dl>
  • Interactive lists <menu>

Ordered lists, unordered lists, and interactive lists contain list items (<li>) which are displayed according to what kind of list we’re dealing with. An ordered list (<ol>) displays numbers next to list items. Unordered lists (<ul>) and menu elements (<menu>) displays bullet points next to list items. We call these “list markers” and they can even be styled using the ::marker pseudo-element. Description lists use description terms (<dt>) and description details (<dd>) instead of <li> and don’t have list markers. They‘re supposed to be used to display metadata and glossaries, but I can’t say I’ve ever seen them in the wild.

Let’s start off with the easy stuff — how to correctly (at least in my opinion) reset list styles. After that, we’ll take a look at a couple of accessibility issues before shining a light on the elusive <menu> element, which you may be surprised to learn… is actually a type of list, too!

Resetting list styles

Browsers automatically apply their own User Agent styles to help with the visual structure of lists right out of the box. That can be great! But if we want to start with a blank slate free of styling opinions, then we have to reset those styles first.

For example, we can remove the markers next to list items pretty easily. Nothing new here:

/* Zap all list markers! */
ol, ul, menu {
  list-style: none;
}

But modern CSS has new ways to help us target specific list instances. Let’s say we want to clear markers from all lists, except if those lists appear in long-form content, like an article. If we combine the powers of newer CSS pseudo-class functions :where() and :not(), we can isolate those instances and allow the markers in those cases:

/* Where there are lists that are not articles where there are lists... */
:where(ol, ul, menu):not(article :where(ol, ul, menu)) {
  list-style: none;
}

Why use :where() instead of :is()? The specificity of :where() is always zero, whereas :is() takes the specificity of the most specific element in its list of selectors. So, using :where() is a less forceful way of overriding things and can be easily overridden itself.

UA styles also apply padding to space a list item’s content from its marker. Again, that’s a pretty nice affordance right out of the box in some cases, but if we’re already removing the list markers like we did above, then we may as well wipe out that padding too. This is another case for :where():

:where(ol, ul, menu) {
  padding-left: 0; /* or padding-inline-start */
}

OK, that’s going to prevent marker-less list items from appearing to float in space. But we sort of tossed out the baby with the bathwater and removed the padding in all instances, including the ones we previously isolated in an <article>. So, now those lists with markers sorta hang off the edge of the content box.

Notice that UA styles apply an extra 40px to the <menu> element.

So what we want to do is prevent the list markers from “hanging” outside the container. We can fix that with the list-style-position property:

Or not… maybe it comes down to stylistic preference?

Newer accessibility concerns with lists

Unfortunately, there are a couple of accessibility concerns when it comes to lists — even in these more modern times. One concern is a result of applying list-style: none; as we did when resetting UA styles.

In a nutshell, Safari does not read ordered and unordered lists styled with list-style: none as actual lists, like when navigating content with a screen reader. In other words, removing the markers also removes the list’s semantic meaning. The fix for this fix it to apply an ARIA list role on the list and a listitem role to the list items so screen readers will pick them up:

<ol style="list-style: none;" role="list">
  <li role="listItem">...</li>
  <li role="listItem">...</li>
  <li role="listItem">...</li>
</ol>

<ul style="list-style: none;" role="list">
  <li role="listItem">...</li>
  <li role="listItem">...</li>
  <li role="listItem">...</li>
</ul>

Oddly, Safari considers this to be a feature rather than a bug. Basically, users would report that screen readers were announcing too many lists (because developers tend to overuse them), so now, only those with role="list" are announced by screen readers, which actually isn’t that odd after all. Scott O’Hara has a detailed rundown of how it all went down.

A second accessibility concern isn’t one of our own making (hooray!). So, you know how you’re supposed to add an aria-label to <section> elements without headings? Well, it sometimes makes sense to do the same with a list that doesn’t contain a heading element that helps describe the list.

<!-- This list is somewhat described by the heading -->
<section>
  <h2>Grocery list</h2>
  <ol role="list">
     <!-- ... -->
  </ol>
</section>

<!-- This list is described by the aria-label -->
<ol role="list" aria-label="Grocery list">
  <!-- ... -->
</ol>

You absolutely don’t have to use either method. Using a heading or an ARIA label is just added context, not a requirement — be sure to test your websites with screen readers and do what offers the best user experience for the situation.

In somewhat related news, Eric Bailey wrote up an excellent piece on why and how he considers aria-label to be a code smell.

Wait, <menu> is a list, too?

OK, so, you’re likely wondering about all of the <menu> elements that I’ve been slipping into the code examples. It’s actually super simple; menus are unordered lists except that they’re meant for interactive items. They’re even exposed to the accessibility tree as unordered lists.

In the early days of the semantic web, I mistakenly believed that menus were like <nav>s before believing that they were for context menus (or “toolbars” as the spec says) because that’s what early versions of the HTML spec said. (MDN has an interesting write-up on all of the deprecated stuff related to <menu> if you’re at all interested.)

Today, however, this is the semantic way to use menus:

<menu aria-label="Share article">
  <li><button>Email</button></li>
  <li><button>Twitter</button></li>
  <li><button>Facebook</button></li>
</menu>

Personally, I think there are some good use-cases for <menu>. That last example shows a list of social sharing buttons wrapped up in a labeled <menu> element, the notable aspect being that the “Share article” label contributes a significant amount of context that helps describe what the buttons do.

Are menus absolutely necessary? No. Are they HTML landmarks? Definitely not. But they’re there if you enjoy fewer <div>s and you feel like the component could use an aria-label for additional context.

Anything else?

Yes, there’s also the aforementioned <dl> (description list) element, however, MDN doesn’t seem to consider them lists in the same way — it’s a list of groups containing terms — and I can’t say that I’ve really seen them in use. According to MDN, they’re supposed to be used for metadata, glossaries, and other types of key-value pairs. I would just avoid them on the grounds that all screen readers announce them differently.

But let’s not end things on a negative note. Here’s a list of super cool things you can do with lists:


Newer Things to Know About Good Ol’ HTML Lists originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Menu to Grid Layout Animation

Today I’d like to share a little layout animation with you. It’s inspired by the design of Sturdy’s client showcase. Initially, we have a row based menu layout which shows some thumbnails on hover. Using the GSAP’s flip plugin, we animate the row to a content preview with larger images which fly to their position in a grid.

Here’s the initial view:

When hovering, some images appear on the right side. Once we click, the thumbnails animate to form a grid and some additional grid items appear:

Here is how it all comes together:

I hope you enjoy this little animation and find it useful!

Stack to Content Layout Transition

Today I’d like to share a little experiment with you that is based on the layout transition of Aristide Benoist’s amazing homepage. Basically, I’m trying to rotate this layout just like Siddarth did in this shot. No WebGL for this experiment so we definitely don’t reach the slickness level of Aristide’s work but it’s fun to try it out.

Our initial scrollable view looks as follows:

Once we click on an item, we animate the stack to the right side, enlarging the items and showing our content:

Here we can now navigate using the arrows. Once we scroll, we move back to the initial stack view.

Here’s the whole flow in a video:

Please keep in mind that this is very experimental and that there might be bugs 😉

I really hope you have fun with this little experiment! Thanks for checking by!

The post Stack to Content Layout Transition appeared first on Codrops.

Letter Shuffle Animation for a Menu

Today I’d like to share a little menu animation with you. It’s an experimental play with letters that are stacked vertically and that animate into a menu by shuffling its letters. The resting letters come in with a slight rotation.

Nothing special, really, but I had to get it out of my head and into a demo 🙂  Hope it gives you some inspiration though!

So the page layout looks as follows:

When clicking on the menu icon on the left, the visible letters will shuffle and reveal the final first letter for each of the menu items:

Let’s see how it all looks in a flow:

Note that this is somewhat experimental and only suited for monospace fonts where we have a fixed/equal width for each letter (unless you’re up for some funky layout, then try it with other fonts). Firefox doesn’t play very nicely here because apparently the line-height is not equally interpreted in some browsers. There might be some tinkering needed with paddings/margins to make it fit properly.

Hope you enjoy this and thanks for checking by!

The post Letter Shuffle Animation for a Menu appeared first on Codrops.

Expanding Rounded Menu Animation

Menu animations are something that can elevate a design to another level. There are endless possibilities and they provide an opportunity to do something unique. Sometimes it’s also interesting to pair them with other animations. Already a while back I saw this really nice menu animation by Ruslan Siiz called “365 Magazine”:

It’s a really beautiful design and animation so I tried replicating it but with more of a dark theme. That dark theme is inspired by another design which I can’t recall (it’s probably from a year ago or so), especially the big letters.

This is the initial page:

When clicking on one of the links in the top menu, two things happen. First, we have a background cover animation which works with an “unreveal” effect. In this tutorial you can learn how this effect works and how to code it up. Second, we have the expanding menu animation in the foreground. This is the how the menu looks like when it’s expanded:

The whole animation looks as follows:

The rounded appearance of the menu is preserved by placing the submenu in a way that it overlaps the top menu. Using an element that wraps the submenu with the background color and border radius, and that has the overflow set to “hidden”, allows us to hide the inner menu element by setting its Y transform to -100%.

I really hope you enjoy this demo and find it inspiring! Let me know what you think via @codrops or @crnacura!

The post Expanding Rounded Menu Animation appeared first on Codrops.

Semantic menu context

Scott digs into the history of the <menu> element. He traced it as far back as HTML 2 (!) in a 1994 changelog. The vibe then, it seems, was to mark up a list. I would suspect the intention is much like <nav> is today, but I really don’t know.

Short story: HTML 4 deprecated it, HTML 5 revived it—this time as a “group of commands”—and then HTML 5.2 deprecated it again. Kind of a bummer since it has some clear use cases.

So, it’s been quite the roller coaster for ol’ <menu>! There never seems to be any easy wins for HTML evolution. As of now, it’s in “don’t bother” territory:

I really wrote this post as a sort of counter point to the often uttered phrase “use semantic HTML and you get accessibility for free!” That statement, on its surface, is largely true. And you should use semantic HTML wherever its use is appropriate. <menu>, unfortunately, doesn’t really give us all that much, even though it has clearly defined semantics. Its intended semantics and what we actually need in reality are better served by either just using the more robust <ul> element, or creating your own role=toolbarmenubar, etc.. Using this semantic element, for semantics sake, is just that.

To Shared LinkPermalink on CSS-Tricks


The post Semantic menu context appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

SVG Overlay and Infinite Menu Background Animation

Today I’d like to share a little menu effect with you. It is composed of two things which is an SVG path overlay animation when it opens (or closes) and an infinite CSS powered background animation of an image grid.

Nothing special really, but I enjoyed putting it together and hopefully it is somehow useful to you!

The SVG path animation for the overlay is based on this demo by Sebastien Gilbert which is a good starter for a nice motion. If you need to adjust paths, I can recommend this fantastic path editor tool by Yann Armelin.

The infinite background animation of the menu is made with a CSS animation. The trick is to have a repeated set of images and once we translate to the visually equal part, we restart the animation.

.tiles {
	position: absolute;
	left: 50%;
	top: 50%;
	height: 150vh;
	display: flex;
	opacity: 0.5;
	flex-direction: column;
	justify-content: center;
	transform: translate3d(-50%,-50%, 0) rotate(22.5deg);
}

.tiles__line {
	display: flex;
	transform: translateX(25%);
	animation: runner 10s linear infinite;
}

.tiles__line:nth-child(2) {
	animation-duration: 16s;
}

.tiles__line:nth-child(3) {
	animation-duration: 22s;
}

@keyframes runner {
	to {
		transform: translateX(-25%);
	}
}

Check out the CSS-Only Marquee Effect, if you’d like to understand the details of this.

And this is how it all comes together:

Hope you enjoy this and find it useful!

The post SVG Overlay and Infinite Menu Background Animation appeared first on Codrops.

Menu and Thumbnail Stack Animation

Today I’d like to share a little menu animation with you. It’s just a simple proof-of-concept to explore how to animate a vertical image stack into a horizontal one. This is incorporated in a menu that also expands its items letter by letter to add some interesting motion.

The initial view is the menu and when we hover an item, the vertical stack appears in the back of the menu with a glitch animation. It changes depending on the current item hovered:

When we click on an item, the letters and the decorative circle expand while the thumbnails of the stack rearrange from a column into a row of images:

The whole motion in action:

I hope you like this demo and find it inspirational!

The post Menu and Thumbnail Stack Animation appeared first on Codrops.

Layout with Reveal Animations and Content Preview

Today I’d like to share a little experiment with you that has some fancy animations for a menu and a content preview. I love to play with the overflow-hidden trick that we can use to make elements disappear and show again (by being cut off). We call this form of hiding an element reveal effect on Codrops and we’ve played with it here, for example.

The idea is to show/hide lines of text fluidly and repeat this animation pattern throughout the design:

Note that this is just an animation proof-of-concept and not a properly made template!

I really hope you like this little experiment and find it inspiring!

The post Layout with Reveal Animations and Content Preview appeared first on Codrops.

How to Code the K72 Marquee Hover Animation

A while back, the folks of K72 released their amazing new website made by the award winning agency Locomotive that boasts with coolness and great design. It has many engaging details but the one I love the most is the fun menu hover effect that involves a marquee:

In this tutorial I’ll show how to create this direction-aware marquee hover effect. We’ll not code the opening animation of the menu itself, but instead focus on animations involved when hovering a menu item.

We won’t be looking under the hood and how the great folks of Locomotive did it but instead, do our version from the visual effect.

Let’s get started!

The Markup

We’ll need a couple of elements to be able to pull off the “reveal” effect. This animation consists of translating one element (where the overflow is hidden) in one direction while moving its child in the opposite direction. The illusion created is that the element reduces its height and gets cut off.

Another structure we need to take care of, is the the one for the marquee. We cover the CSS-only marquee animation in this tutorial. So the structure will be similar but we’ll simplify things a bit style-wise (we won’t have an offset for the items) so less “calculations” will be needed.

So this is the markup we’ll set up for the menu and a menu item:

<nav class="menu">
	<div class="menu__item">
		<a class="menu__item-link">Guayaquil</a>
		<div class="marquee">
			<div class="marquee__inner-wrap">
				<div class="marquee__inner" aria-hidden="true">
					<span>Frank Tower</span>
					<div class="marquee__img" style="background-image:url(img/1.jpg);"></div>
					<span>Dom Dom</span>
					<div class="marquee__img" style="background-image:url(img/2.jpg);"></div>
					<span>Santa Maria</span>
					<div class="marquee__img" style="background-image:url(img/3.jpg);"></div>
					<span>Big Molly</span>
					<div class="marquee__img" style="background-image:url(img/4.jpg);"></div>
					<span>Frank Tower</span>
					<div class="marquee__img" style="background-image:url(img/1.jpg);"></div>
					<span>Dom Dom</span>
					<div class="marquee__img" style="background-image:url(img/2.jpg);"></div>
					<span>Santa Maria</span>
					<div class="marquee__img" style="background-image:url(img/3.jpg);"></div>
					<span>Big Molly</span>
					<div class="marquee__img" style="background-image:url(img/4.jpg);"></div>
				</div><!--/marquee__inner-->
			</div><!--/marquee__inner-wrap-->
		</div><!--/marquee-->
	</div><!--/menu__item-->
	<!-- ... -->
</nav><!--/menu-->

For the looping marquee animation, we duplicate our content. Let’s look into the details for that in a moment.

The marquee element and its child, marquee__inner-wrap, will be used for the cut off reveal effect.

Let’s now take care of the styling.

The CSS

We’ll start by styling the menu item:

.menu__item {
	cursor: default;
	position: relative;
	overflow: hidden;
	text-align: center;
	box-shadow: 0 -1px var(--color-border);
}

.menu__item:last-child {
	box-shadow: 0 1px var(--color-border), 0 -1px var(--color-border);
}

Since we want the little border to be visible when moving over to another item, we’ll use a box shadow. The variables are defined in the body styles.

What is important here is that the element’s overflow is set to “hidden” because we’ll be sliding the inner elements up and down and we don’t want to see them.

The link is styled simply and we also take care of focus styles:

.menu__item-link {
	display: block;
	position: relative;
	cursor: pointer;
	text-decoration: none;
}

.menu__item-link:focus,
.menu__item-link:focus-visible {
	color: var(--menu-focus);
}

.menu__item-link:focus:not(:focus-visible) {
	color: var(--color-link);
}

The marquee will be positioned absolutely and we’ll translate it down by default, while the child will be translated up. When hovering, we’ll reset these translations dynamically using JavaScript depending on where we come from with the mouse:

.marquee {
	position: absolute;
	top: 0;
	left: 0;
	overflow: hidden;
	width: 100%;
	height: 100%;
	pointer-events: none;
	background: var(--marquee-bg);
	transform: translate3d(0,101%,0);
}

.marquee__inner-wrap {
	height: 100%;
	width: 100%;
	transform: translate3d(0,-101%,0);
}

The inner marquee element will be as large as its content and we’ll have an animation running:

.marquee__inner {
	height: 100%;
	width: fit-content;
	align-items: center;
	display: flex;
	position: relative;
	animation: marquee 15s linear infinite;
	will-change: transform;
}

@keyframes marquee {
	100% {
		transform: translate3d(-50%, 0, 0);
	}
}

Since we doubled the content, we know exactly when we have to “restart” the animation. At half of the element’s width, we’ll go back to the beginning, creating the illusion of an endless flow.

And finally, some styling for our text elements and the images:

.menu__item-link,
.marquee span {
	white-space: nowrap;
	font-size: 6vw;
	line-height: 1.2;
	font-weight: 600;
	padding: 1vh 1vw 0;
	text-transform: uppercase;
}

.marquee span {
	text-align: center;
	color: var(--marquee-text);
	font-weight: 400;
}

.marquee__img {
	width: 15vw;
	height: 70%;
	margin: 0 2vw;
	border-radius: 5vw;
	background-size: cover;
	background-position: 50% 50%;
}

And that’s all the styling! Let’s now take care of the dynamic part.

The JavaScript

The core of our script is the changing of the transforms based on the direction we are coming from with the mouse. John Stewart coded an elegant solution for this and we’ll integrate his code into our script. We’ll use GSAP.

Let’s first create our entry file (index.js) and initialize our Menu:

import { Menu } from './menu';
// initialize the menu
new Menu(document.querySelector('.menu'));

The Menu has a set of items:

import { MenuItem } from './menuItem';

export class Menu {
    constructor(el) {
        // .menu element
        this.DOM = {el: el};
        // the menu items
        this.DOM.menuItems = this.DOM.el.querySelectorAll('.menu__item');
        // array of MenuItem
        this.menuItems = [];
        this.DOM.menuItems.forEach(menuItem => this.menuItems.push(new MenuItem(menuItem)));
    }
}

We initialize a MenuItem instance for each of the menu’s items.

Now let’s create a class MenuItem where we add the mouse enter/leave logic. We want to animate both the .marquee and .marquee__inner-wrap elements when hovering over the .menu__item-link element. These two elements need to be translated in different directions so that we achieve the cut-off reveal effect.

Let’s start by initializing some elements and events:

import { gsap } from 'gsap';
import { closestEdge } from './utils';

export class MenuItem {
    constructor(el) {
        // .menu__item element
        this.DOM = {el: el};
        // .menu__item-link element
        this.DOM.link = this.DOM.el.querySelector('a.menu__item-link');
        // .marquee element
        this.DOM.marquee = this.DOM.el.querySelector('.marquee');
        // .marquee__inner-wrap element
        this.DOM.marqueeInner = this.DOM.marquee.querySelector('.marquee__inner-wrap');
        // some default options for the animation's speed and easing
        this.animationDefaults = {duration: 0.6, ease: 'expo'};
        // events initialization
        this.initEvents();
    }
    initEvents() {
        this.onMouseEnterFn = ev => this.mouseEnter(ev);
        this.DOM.link.addEventListener('mouseenter', this.onMouseEnterFn);
        this.onMouseLeaveFn = ev => this.mouseLeave(ev);
        this.DOM.link.addEventListener('mouseleave', this.onMouseLeaveFn);
    }
    // ...
}

When hovering in or out, we want the marquee content to be revealed by sliding out both, the marquee and marqueeInner elements. This animation should follow the mouse movement, meaning that if we enter the element from the top then the sliding effect will be from top to bottom and vice-versa. To achieve this, we need to set up the correct initial positions for both elements:

export class MenuItem {
    // ...
    mouseEnter(ev) {
        // find closest side to the mouse
        const edge = this.findClosestEdge(ev);
        
        // set the initial y position for both the marquee and marqueeInner elements
        // for the reveal effect to happen, both start at opposite positions
        // the directions are different depending on the direction the cursor enters the element (bottom or top)
        gsap.timeline({defaults: this.animationDefaults})
        .set(this.DOM.marquee, {y: edge === 'top' ? '-101%' : '101%'}, 0)
        .set(this.DOM.marqueeInner, {y: edge === 'top' ? '101%' : '-101%'}, 0)
        .to([this.DOM.marquee, this.DOM.marqueeInner], {y: '0%'}, 0);
    }
    mouseLeave(ev) {
        // find closest side to the mouse
        const edge = this.findClosestEdge(ev);
        
        gsap.timeline({defaults: this.animationDefaults})
        .to(this.DOM.marquee, {y: edge === 'top' ? '-101%' : '101%'}, 0)
        .to(this.DOM.marqueeInner, {y: edge === 'top' ? '101%' : '-101%'}, 0);
    }
    // find closest side to the mouse when entering/leaving
    findClosestEdge(ev) {
        const x = ev.pageX - this.DOM.el.offsetLeft;
        const y = ev.pageY - this.DOM.el.offsetTop;
        return closestEdge(x,y,this.DOM.el.clientWidth, this.DOM.el.clientHeight);
    }
    // ...
}

And that’s all! Our direction-aware marquee hover effect is done!

Check out the final demo.

Now, if you’d like another challenge, try to implement the opening/closing of the menu. The Locomotive team used a really great 3D effect here, so go on and try that or experiment with other cool “openings”.

I really hope you enjoyed this tutorial and found it useful!

The post How to Code the K72 Marquee Hover Animation appeared first on Codrops.

Inline to Menu Link Animation

Inspired by this fantastic Dribbble shot by Matthew Hall, I wanted to experiment with this kind of inline link to menu block animation. So here’s a little experimental effect that does exactly that and then shows some images.

Here is Matthew’s original animation:

“Image Carousel” by Matthew Hall

With the focus on recreating the inline link to menu link animation, I also wanted to explore some kind of animations on the images. I found the staggering appearance the most fitting on here, but there are lots of possibilities.

So, the initial content view looks as follows:

When clicking on one of the inline links, each link moves to the right while all the other text moves to the left and disappears:

So here’s the result of the whole concept:

I really hope you enjoy this and find it inspirational!

Thanks for checking by and let me know your feedback @crnacura or @codrops.

The post Inline to Menu Link Animation appeared first on Codrops.

How to Code a Crosshair Mouse Cursor with Distortion Hover Effect

Today I’d like to show you how to code a special cursor effect. Custom cursors have been very popular and there’s so many creative possibilities that can enhance a certain design and an interaction logic.

Let’s have a look how to create a fullscreen crosshair cursor in SVG and how to distort the cursors’s lines with an SVG filter when hovering over links. We’ll also add a nice hover animation for some menu items using Splitting.js.

The Markup

For the SVG cursor we want a singe SVG for each line that has enough of space to get the distortion effect applied to it:

<div class="cursor">
	<svg class="cursor__line cursor__line--horizontal" viewBox="0 0 200 20" preserveAspectRatio="none">
		<line class="cursor__line-element" x1="0" y1="10" x2="200" y2="10" shape-rendering="crispEdges" vector-effect="non-scaling-stroke" />
	</svg>
	<svg class="cursor__line cursor__line--vertical" viewBox="0 0 20 200" preserveAspectRatio="none">
		<line class="cursor__line-element" x1="10" y1="0" x2="10" y2="200" shape-rendering="crispEdges" vector-effect="non-scaling-stroke" />
	</svg>
</div>

We’ll add the filters like this:

<div class="cursor">
	<svg class="cursor__line cursor__line--horizontal" viewBox="0 0 200 20" preserveAspectRatio="none">
		<defs>
			<filter id="filter-noise-x" x="-50%" y="-50%" width="200%" height="200%" 
			filterUnits="objectBoundingBox">
				<feTurbulence type="fractalNoise" baseFrequency="0" numOctaves="1" result="warp" />
				<feOffset dx="-30" result="warpOffset" />
				<feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="30" in="SourceGraphic" in2="warpOffset" />
			</filter>
		</defs>
		<line class="cursor__line-element" x1="0" y1="10" x2="200" y2="10" shape-rendering="crispEdges" vector-effect="non-scaling-stroke" />
	</svg>
	<svg class="cursor__line cursor__line--vertical" viewBox="0 0 20 200" preserveAspectRatio="none">
		<defs>
			<filter id="filter-noise-y" x="-50%" y="-50%" width="200%" height="200%" 
			filterUnits="objectBoundingBox">
				<feTurbulence type="fractalNoise" baseFrequency="0" numOctaves="1" result="warp" />
				<feOffset dy="-30" result="warpOffset" />
				<feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="30" in="SourceGraphic" in2="warpOffset" />
			</filter>
		</defs>
		<line class="cursor__line-element" x1="10" y1="0" x2="10" y2="200" shape-rendering="crispEdges" vector-effect="non-scaling-stroke" />
	</svg>
</div>

Let’s set up our menu with some data-splitting attributes:

<nav class="menu">
	<a href="#content-1" class="menu__item">
		<span data-splitting class="menu__item-title">Maputo</span>
		<span data-splitting class="menu__item-sub">Nights</span>
	</a>
	<a href="#content-1" class="menu__item">
		<span data-splitting class="menu__item-title">Gaborone</span>
		<span data-splitting class="menu__item-sub">Vibes</span>
	</a>
	<a href="#content-1" class="menu__item">
		<span data-splitting class="menu__item-title">Kinshasa</span>
		<span data-splitting class="menu__item-sub">Walks</span>
	</a>
</nav>

The CSS

First, we need to hide our cursor by default, and we just want to show it if the user has a pointing device, like a mouse. So we add a media query with the any-pointer media feature:

.cursor {
	display: block;
}

@media (any-pointer:fine) {
	.cursor {
		position: fixed;
		top: 0;
		left: 0;
		display: block;
		pointer-events: none;
		z-index: 1001;
	}

	.no-js .cursor {
		display: none;
	}

	.cursor__line {
		position: fixed;
		display: block;
		will-change: transform, opacity;
	}
	
	.cursor__line--horizontal {
		top: -10px;
		left: -10%;
		width: 120%;
		height: 20px;
	}
	
	.cursor__line--vertical {
		left: -10px;
		top: -10%;
		height: 120%;
		width: 20px;
	}
	
	.cursor__line-element {
		fill: none;
		stroke: var(--cursor-stroke);
		stroke-width: var(--cursor-stroke-width);
	}

}

The variables are define in the body.

For the menu, we’ll use some flexbox magic to lay out the menu items beneath each other:

.menu {
	display: flex;
	flex-direction: column;
	width: 100vw;
	height: calc(100vh - 13rem);
	position: relative;
	justify-content: flex-start;
	align-items: center;
}

.menu {
	text-align: center;
	padding-top: 10vh;
}

.menu__item {
	display: inline-block;
	margin-bottom: 3rem;
	text-decoration: none;
	color: var(--color-menu);
	font-family: vortice-concept, sans-serif;
}

.menu__item-title {
	line-height: 1;
	font-size: 7.5vw;
}

.menu__item-sub {
	font-size: 1.5vw;
	display: block;
}

@media screen and (min-width: 53em) {
	.menu {
		height: 100vh;
		justify-content: center;
	}
}

The JavaScript

Let’s create our custom cursor. So we have two SVGs, one for each line. As we saw in the markup earlier, each one of the SVGs will include a filter that we’ll apply to the respective line when hovering over a menu link.

Let’s start coding the entry JavaScript file (index.js):


import { Cursor } from './cursor';

// initialize custom cursor
const cursor = new Cursor(document.querySelector('.cursor'));

// mouse effects on all links
[...document.querySelectorAll('a')].forEach(link => {
    link.addEventListener('mouseenter', () => cursor.enter());
    link.addEventListener('mouseleave', () => cursor.leave());
});

Now, let’s create a class for the cursor (in cursor.js):


import { gsap } from 'gsap';
import { getMousePos } from './utils';

// Track the mouse position and update it on mouse move
let mouse = {x: 0, y: 0};
window.addEventListener('mousemove', ev => mouse = getMousePos(ev));

export class Cursor {
    constructor(el) {
    }
    // hovering over a link
    enter() {
    }
    // hovering out a link
    leave() {
    }
    // create the turbulence animation timeline on the cursor line elements
    createNoiseTimeline() {
    }
    // render styles and loop
    render() {
        // ...
        requestAnimationFrame(() => this.render());
    }
}

What we do here is to update the mouse position as we move the mouse around. For that, we use the getMousePos function (in utils.js).

Let’s move on to the next interesting part:


...
constructor(el) {
    // main DOM element which includes the 2 svgs, each for each line
    this.DOM = {el: el};
    // both horizontal and vertical lines
    this.DOM.lines = this.DOM.el.children;
    [this.DOM.lineHorizontal, this.DOM.lineVertical] = this.DOM.lines;
    // hide initially
    gsap.set(this.DOM.lines, {opacity: 0});
    ...
}
...

We initialize the line DOM elements and hide them initially.

We want to update the lines transform (translation values) as we move the mouse. For that, let’s create an object that stores the translation state:


...
constructor(el) {
    ...
    // style properties that will change as we move the mouse (translation)
    this.renderedStyles = {
        tx: {previous: 0, current: 0, amt: 0.15},
        ty: {previous: 0, current: 0, amt: 0.15}
    };
    ...
}
...

With interpolation, we can achieve a smooth animation effect when moving the mouse. The “previous” and “current” values are the values we’ll be interpolating. The current value of one of these “animatable” properties will be one between these two values at a specific increment. The value of “amt” is the amount to interpolate. As an example, the following formula calculates our current translationX value:

this.renderedStyles.tx.previous = lerp(this.renderedStyles.tx.previous, this.renderedStyles.tx.current, this.renderedStyles.tx.amt);

...
constructor(el) {
    ...
    // svg filters (ids)
    this.filterId = {
        x: '#filter-noise-x',
        y: '#filter-noise-y'
    };
    // the feTurbulence elements per filter
    this.DOM.feTurbulence = {
        x: document.querySelector(`${this.filterId.x} > feTurbulence`),
        y: document.querySelector(`${this.filterId.y} > feTurbulence`)
    }
    // turbulence current value
    this.primitiveValues = {turbulence: 0};
    // create the gsap timeline that will animate the turbulence value
    this.createNoiseTimeline();
}
...

Next, we initialize the filter ids, the feTurbulence elements for each SVG filter (one per line) and also the current turbulence value. Then we create the GSAP timeline that will take care of updating the baseFrequency of each filter with the current turbulence value. Here’s how that timeline and the methods that start/stop it look like:


...
createNoiseTimeline() {
    // turbulence value animation timeline:
    this.tl = gsap.timeline({
        paused: true,
        onStart: () => {
            // apply the filters for each line element
            this.DOM.lineHorizontal.style.filter = `url(${this.filterId.x}`;
            this.DOM.lineVertical.style.filter = `url(${this.filterId.y}`;
        },
        onUpdate: () => {
            // set the baseFrequency attribute for each line with the current turbulence value
            this.DOM.feTurbulence.x.setAttribute('baseFrequency', this.primitiveValues.turbulence);
            this.DOM.feTurbulence.y.setAttribute('baseFrequency', this.primitiveValues.turbulence);
        },
        onComplete: () => {
            // remove the filters once the animation completes
            this.DOM.lineHorizontal.style.filter = this.DOM.lineVertical.style.filter = 'none';
        }
    })
    .to(this.primitiveValues, { 
        duration: 0.5,
        ease: 'power1',
        // turbulence start value
        startAt: {turbulence: 1},
        // animate to 0
        turbulence: 0
    });
}
enter() {
    // start the turbulence timeline
    this.tl.restart();
}
leave() {
    // stop the turbulence timeline
    this.tl.progress(1).kill();
}
...

The animation will change the turbulence value (which starts at 1 and ends at 0) and apply it to each feTurbulence’s baseFrequency attribute. The filters get applied to the lines in the beginning and removed once the animation is completed.

To finalize the constructor method we fade in the lines and start updating the translation values the first time we move the mouse:


...
constructor(el) {
    ...
    import { lerp, getMousePos } from './utils';
    ...
    // on first mousemove fade in the lines and start the requestAnimationFrame rendering function
    this.onMouseMoveEv = () => {
        this.renderedStyles.tx.previous = this.renderedStyles.tx.current = mouse.x;
        this.renderedStyles.ty.previous = this.renderedStyles.ty.previous = mouse.y;
        gsap.to(this.DOM.lines, {duration: 0.9, ease: 'Power3.easeOut', opacity: 1});
        requestAnimationFrame(() => this.render());
        window.removeEventListener('mousemove', this.onMouseMoveEv);
    };
    window.addEventListener('mousemove', this.onMouseMoveEv);
}
...

Now we’re only missing the actual method that updates the lines’ translation values as we move the mouse:



...
render() {
    // update the current translation values
    this.renderedStyles['tx'].current = mouse.x;
    this.renderedStyles['ty'].current = mouse.y;
    // use linear interpolation to delay the translation animation
    for (const key in this.renderedStyles ) {
        this.renderedStyles[key].previous = lerp(this.renderedStyles[key].previous, this.renderedStyles[key].current, this.renderedStyles[key].amt);
    }
    // set the new values
    gsap.set(this.DOM.lineVertical, {x: this.renderedStyles['tx'].previous});
    gsap.set(this.DOM.lineHorizontal, {y: this.renderedStyles['ty'].previous});
    // loop this until the end of time
    requestAnimationFrame(() => this.render());
}

As an extra, let’s add a little glitch effect to the menu items texts when we hover over them. We’ll use the Splitting library to split the menu texts into spans/chars so we can animate each one individually. We want to change the translation values of each character and also it’s color. Let’s update our index.js file:


import { Cursor } from './cursor';
import { MenuItem } from './menuItem';
// Splitting (used to split the menu item texts to spans/characters)
import 'splitting/dist/splitting.css';
import 'splitting/dist/splitting-cells.css';
import Splitting from 'splitting';

// initialize Splitting
const splitting = Splitting();

// initialize custom cursor
const cursor = new Cursor(document.querySelector('.cursor'));

// Menu Items
[...document.querySelectorAll('.menu > a')].forEach(el => new MenuItem(el));

// mouse effects on all links
[...document.querySelectorAll('a')].forEach(link => {
    link.addEventListener('mouseenter', () => cursor.enter());
    link.addEventListener('mouseleave', () => cursor.leave());
});

Assuming we have data-splitting set in all elements we want to split into chars, then we only need to call Splitting() and we then have each text split into a bunch of spans, for every letter of the text.

Let’s now have a look at our MenuItem class:


import { gsap } from 'gsap';

export class MenuItem {
    constructor(el) {
        this.DOM = {el};
        // all text chars (Splittingjs) 
        this.DOM.titleChars = this.DOM.el.querySelectorAll('span.char');
        // initial and final colors for each span char (before and after hovering)
        const bodyComputedStyle = getComputedStyle(document.body);
        this.colors = {
            initial: bodyComputedStyle.getPropertyValue('--color-menu'), 
            final: bodyComputedStyle.getPropertyValue('--color-link')
        };
        this.initEvents();
    }
    ...
}

We get a reference to all the characters of the menu item text and also it’s initial and final colors for the hover animation.


...
initEvents() {
    this.onMouseEnterEv = () => this.onMouseEnter();
    this.DOM.el.addEventListener('mouseenter', this.onMouseEnterEv);

    this.onMouseLeaveEv = () => this.onMouseLeave();
    this.DOM.el.addEventListener('mouseleave', this.onMouseLeaveEv);
}
...

We initialize the mouseenter/mouseleave events which will triggger the animation on the characters.

When hovering over a menu item we will randomly change its characters position and color, and when hovering out we reset the original color:

onMouseEnter() {
    if ( this.leaveTimeline ) {
        this.leaveTimeline.kill();
    }

    // let's try to do an animation that resembles a glitch effect on the characters
    // we randomly set new positions for the translation and rotation values of each char and also set a new color
    // and repeat this for 3 times
    this.enterTimeline = gsap.timeline({
        defaults: {
            duration: 0.05,
            ease: 'power3',
            x: () => gsap.utils.random(-15, 15),
            y: () => gsap.utils.random(-20, 10),
            rotation: () => gsap.utils.random(-5, 5),
            color: () => gsap.utils.random(0, 3) < 0.5 ? this.colors.final : this.colors.initial
        }
    })
    // repeat 3 times (repeatRefresh option will make sure the translation/rotation values will be different for each iteration)
    .to(this.DOM.titleChars, {
        repeat: 3,
        repeatRefresh: true
    }, 0)
    // reset translation/rotation and set final color
    .to(this.DOM.titleChars, {
        x: 0, 
        y: 0, 
        rotation: 0,
        color: this.colors.final
    }, '+=0.05');
}
onMouseLeave() {
    // set back the initial color for each char
    this.leaveTimeline = gsap.timeline()
    .to(this.DOM.titleChars, {
        duration: 0.4,
        ease: 'power3',
        color: this.colors.initial
    });
}

And that is all!

I hope this has not been too difficult to follow and that you have gained some insight into constructing this fancy effect.

Please let me know if you have any question @codrops or @crnacura.

Thank you for reading!

The post How to Code a Crosshair Mouse Cursor with Distortion Hover Effect appeared first on Codrops.

Rotated 3D Letters and Image Hover Effect

Some months ago, I wrote about how to achieve a hover effect for a menu where an image would appear for each item. Then we saw how to apply this in Exploring Animations for Menu Hover Effects. When I discovered the fantastic site of One up Studio I wanted to combine their cool 3D-ish menu hover effect with that previous animation, so this is a little fusion between the two.

The 3D motion is slightly different and an image is shown in an angle, creating a playful look.

I really hope you like this little experiment and find it useful. Thanks for visiting!

The post Rotated 3D Letters and Image Hover Effect appeared first on Codrops.

How We Improved the Accessibility of Our Single Page App Menu

I recently started working on a Progressive Web App (PWA) for a client with my team. We’re using React with client-side routing via React Router, and one of the first elements that we made was the main menu. Menus are a key component of any site or app. That’s really how folks get around, so making it accessible was a super high priority for the team.

But in the process, we learned that making an accessible main menu in a PWA isn’t as obvious as it might sound. I thought I’d share some of those lessons with you and how we overcame them.

As far as requirements go, we wanted a menu that users could not only navigate using a mouse, but using a keyboard as well, the acceptance criteria being that a user should be able to tab through the top-level menu items, and the sub-menu items that would otherwise only be visible if a user with a mouse hovered over a top-level menu item. And, of course, we wanted a focus ring to follow the elements that have focus.

The first thing we had to do was update the existing CSS that was set up to reveal a sub-menu when a top-level menu item is hovered. We were previously using the visibility property, changing between visible and hidden on the parent container’s hovered state. This works fine for mouse users, but for keyboard users, focus doesn’t automatically move to an element that is set to visibility: hidden (the same applies for elements that are given display: none). So we removed the visibility property, and instead used a very large negative position value:

.menu-item {
  position: relative;
}

.sub-menu {
  position: absolute
  left: -100000px; /* Kicking off  the page instead of hiding visiblity */
}

.menu-item:hover .sub-menu {
  left: 0;
}

This works perfectly fine for mouse users. But for keyboard users, the sub menu still wasn’t visible even though focus was within that sub menu! In order to make the sub-menu visible when an element within it has focus, we needed to make use of :focus and :focus-within on the parent container:

.menu-item {
  position: relative;
}

.sub-menu {
  position: absolute
  left: -100000px;
}

.menu-item:hover .sub-menu,
.menu-item:focus .sub-menu,
.menu-item:focus-within .sub-menu {
  left: 0;
}

This updated code allows the the sub-menus to appear as each of the links within that menu gets focus. As soon as focus moves to the next sub menu, the first one hides, and the second becomes visible. Perfect! We considered this task complete, so a pull request was created and it was merged into the main branch.

But then we used the menu ourselves the next day in staging to create another page and ran into a problem. Upon selecting a menu item—regardless of whether it’s a click or a tab—the menu itself wouldn’t hide. Mouse users would have to click off to the side in some white space to clear the focus, and keyboard users were completely stuck! They couldn’t hit the esc key to clear focus, nor any other key combination. Instead, keyboard users would have to press the tab key enough times to move the focus through the menu and onto another element that didn’t cause a large drop down to obscure their view.

The reason the menu would stay visible is because the selected menu item retained focus. Client-side routing in a Single Page Application (SPA) means that only a part of the page will update; there isn’t a full page reload.

There was another issue we noticed: it was difficult for a keyboard user to use our “Jump to Content” link. Web users typically expect that pressing the tab key once will highlight a “Jump to Content” link, but our menu implementation broke that. We had to come up with a pattern to effectively replicate the “focus clearing” that browsers would otherwise give us for free on a full page reload.

The first option we tried was the easiest: Add an onClick prop to React Router’s Link component, calling document.activeElement.blur() when a link in the menu is selected:

const Menu = () => {
  const clearFocus = () => {
    document.activeElement.blur();
  }

  return (
    <ul className="menu">
      <li className="menu-item">
        <Link to="/" onClick={clearFocus}>Home</Link>
      </li>
      <li className="menu-item">
        <Link to="/products" onClick={clearFocus}>Products</Link>
        <ul className="sub-menu">
          <li>
            <Link to="/products/tops" onClick={clearFocus}>Tops</Link>
          </li>
          <li>
            <Link to="/products/bottoms" onClick={clearFocus}>Bottoms</Link>
          </li>
          <li>
            <Link to="/products/accessories" onClick={clearFocus}>Accessories</Link>
          </li>
        </ul>
      </li>
    </ul>
  );
}

This approach worked well for “closing” the menu after an item is clicked. However, if a keyboard user pressed the tab key after selecting one of the menu links, then the next link would become focused. As mentioned earlier, pressing the tab key after a navigation event would ideally focus on the “Jump to Content” link first.

At this point, we knew we were going to have to programmatically force focus to another element, preferably one that’s high up in the DOM. That way, when a user starts tabbing after a navigation event, they’ll arrive at or near the top of the page, similiar to a full page reload, making it much easier to access the jump link.

We initially tried to force focus on the <body> element itself, but this didn’t work as the body isn’t something the user can interact with. There wasn’t a way for it to receive focus.

The next idea was to force focus on the logo in the header, as this itself is just a link back to the home page and can receive focus. However, in this particular case, the logo was below the “Jump To Content” link in the DOM, which means that a user would have to shift + tab to get to it. No good.

We finally decided that we had to render an interact-able element, for example, an anchor element, in the DOM, at a point that’s above than the “Jump to Content” link. This new anchor element would be styled so that it’s invisible and that users are unable to focus on it using “normal” web interactions (i.e. it’s taken out of the normal tab flow). When a user selects a menu item, focus would be programmatically forced to this new anchor element, which means that pressing tab again would focus directly on the “Jump to Content” link. It also meant that the sub-menu would immediately hide itself once a menu item is selected.

const App = () => {
  const focusResetRef = React.useRef();

  const handleResetFocus = () => {
    focusResetRef.current.focus();
  };

  return (
    <Fragment>
      <a
        ref={focusResetRef}
        href="javascript:void(0)"
        tabIndex="-1"
        style={{ position: "fixed", top: "-10000px" }}
        aria-hidden
      >Focus Reset</a>
      <a href="#main" className="jump-to-content-a11y-styles">Jump To Content</a>
      <Menu onSelectMenuItem={handleResetFocus} />
      ...
    </Fragment>
  )
}

Some notes of this new “Focus Reset” anchor element:

  • href is set to javascript:void(0) so that if a user manages to interact with the element, nothing actually happens. For example, if a user presses the return key immediately after selecting a menu item, that will trigger the interaction. In that instance, we don’t want the page to do anything, or the URL to change.
  • tabIndex is set to -1 so that a user can’t “normally” move focus to this element. It also means that the first time a user presses the tab key upon loading a page, this element won’t be focused, but the “Jump To Content” link instead.
  • style simply moves the element out of the viewport. Setting to position: fixed ensures it’s taken out of the document flow, so there isn’t any vertical space allocated to the element
  • aria-hidden tells screen readers that this element isn’t important, so don’t announce it to users

But we figured we could improve this even further! Let’s imagine we have a mega menu, and the menu doesn’t hide automatically when a mouse user clicks a link. That’s going to cause frustration. A user will have to precisely move their mouse to a section of the page that doesn’t contain the menu in order to clear the :hover state, and therefore allow the menu to close.

What we need is to “force clear” the hover state. We can do that with the help of React and a clearHover class:

// Menu.jsx
const Menu = (props) => {
  const { onSelectMenuItem } = props;
  const [clearHover, setClearHover] = React.useState(false);

  const closeMenu= () => {
    onSelectMenuItem();
    setClearHover(true);
  }

  React.useEffect(() => {
    let timeout;
    if (clearHover) {
      timeout = setTimeout(() => {
        setClearHover(false);
      }, 0); // Adjust this timeout to suit the applications' needs
    }
    return () => clearTimeout(timeout);
  }, [clearHover]);

  return (
    <ul className={`menu ${clearHover ? "clearHover" : ""}`}>
      <li className="menu-item">
        <Link to="/" onClick={closeMenu}>Home</Link>
      </li>
      <li className="menu-item">
        <Link to="/products" onClick={closeMenu}>Products</Link>
        <ul className="sub-menu">
          {/* Sub Menu Items */}
        </ul>
      </li>
    </ul>
  );
}

This updated code hides the menu immediately when a menu item is clicked. It also hides immediately when a keyboard user selects a menu item. Pressing the tab key after selecting a navigation link moves the focus to the “Jump to Content” link.

At this point, our team had updated the menu component to a point where we were super happy. Both keyboard and mouse users get a consistent experience, and that experience follows what a browser does by default for a full page reload.

Our actual implementation is slightly different than the example here so we could use the pattern on other projects. We put it into a React Context, with the Provider set to wrap the Header component, and the Focus Reset element being automatically added just before the Provider’s children. That way, the element is placed before the “Jump to Content” link in the DOM hierarchy. It also allows us to access the focus reset function with a simple hook, instead of having to prop drill it.

We have created a Code Sandbox that allows you to play with the three different solutions we covered here. You’ll definitely see the pain points of the earlier implementation, and then see how much better the end result feels!

We would love to hear feedback on this implementation! We think it’s going to work well, but it hasn’t been released to in the wild yet, so we don’t have definitive data or user feedback. We’re certainly not a11y experts, just doing our best with what we do know, and are very open and willing to learn more on the topic.


The post How We Improved the Accessibility of Our Single Page App Menu appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.