Hire a web Developer and Designer to upgrade and boost your online presence with cutting edge Technologies

Saturday, September 23, 2023

Facilitating Inclusive Online Workshops (Part 2)

 Running a workshop can be an effective alternative to traditional, long-standing meetings. However, if workshops aren’t designed with inclusivity in mind, participants may feel apprehensive about contributing, fearing criticism from others. To help ensure the success of a workshop, Ben Shih introduces the concept of an inclusive workshop. In Part 2 of the series, you will continue to delve deeper into several key principles and guidelines that you can follow during and after the workshop to encourage an inclusive atmosphere.

Earlier in the first part of the series, we defined inclusivity and how it contributes to enriching the workshop experience. We established that inclusivity is about ensuring everyone has an equal opportunity to participate and contribute, regardless of their background or identity. It goes beyond merely having diversity in attendance. It’s about creating an environment where different perspectives are valued and used to drive innovative outcomes.

In the second part, I will introduce you to the principle of the inclusive workshop through the acronym P.A.R.T.S. (which stands for Promote, Acknowledge, Respect, Transparency, and Share). After the principle is explained, we will dive into what you can do during and after the workshop to implement this principle.

The P.A.R.T.S. Principle #

Often, we fall into the trap of thinking, “I’ve got a mixed group of folks here. My inclusivity job is done!”

Yes, having a diverse set of individuals is often an essential first step. But it’s just that — a first step. It’s like opening the door and inviting people in. However, the real task begins after the guests have arrived. That’s when you need to ensure they feel welcome, heard, and valued.

As a facilitator, how can you make sure that people feel safe to express their ideas and participate actively during the workshop? Here’s where the P.A.R.T.S. principle comes in.

The P.A.R.T.S. principle is an acronym that encapsulates five key principles that can form the foundation of any inclusive workshop: Promote, Acknowledge, Respect, Transparency, and Share.

P — Promote #

Promote active participation from all attendees.

This begins with creating an environment where participants feel at ease sharing their ideas, opinions, and experiences. As a facilitator, your role is to set this tone from the beginning. One practical way to promote participation is by establishing some ground rules that encourage everyone to contribute. Another approach is to use different facilitation techniques to draw out quieter participants, such as having a quiet brainstorming session where participants can spend more time on their own to contribute their ideas or having round-robin techniques where everyone gets a turn to speak.

A — Acknowledge #

Acknowledging participants’ contributions validates their input and makes them feel heard and valued.

This can be as simple as saying, “Thank you for sharing,” or “That’s an interesting perspective.” It’s also about demonstrating that you’ve understood their input by summarizing or paraphrasing what they’ve said. By doing this, you not only confirm their feelings of being heard but also model listening behavior for other participants.

R — Respect #

Respect for all ideas, experiences, and perspectives is fundamental to an inclusive workshop.

This starts with setting expectations that all ideas are welcome, no matter how outside-the-box they may seem. It also means respecting the varied communication styles, personalities, and cultural backgrounds of the participants. As a facilitator, you should encourage respect by addressing any inappropriate comments or behaviors immediately and decisively.

T — Transparency #

Transparency involves clear and open communication.

As a facilitator, it’s essential to articulate the workshop’s goals and processes clearly, address questions and concerns promptly, and keep channels for feedback open and responsive. This can be done by stating the agenda upfront, explaining the purpose of each activity, and regularly checking in with participants to ensure they’re following along.

S — Share #

Share the workshop’s objectives, expectations, and agenda with all participants.

This shared understanding guides the workshop process and provides a sense of direction. It also empowers participants to take ownership of their contributions and the workshop outcomes.

The P.A.R.T.S. principle is a high-level principle you can try to implement in your workshop to make sure that all voices are heard, but to guide you further into how the principle can be used, here are some practical steps you can follow before, during, and after the workshop.

Applying The P.A.R.T.S. Principle: Before And During The Workshop #

Step 1. Set The Stage #

Setting the stage for your workshop goes beyond just a simple introduction. This is the point at which you establish the environment and set the tone for the entire event. For example, you can set rules like: “One person speaks at a time,” “Respect all ideas,” “Challenge the idea, not the person,” and so on. Clearly stating these rules before you start will help create an environment conducive to open and productive discussions.

A screenshot of an example of how ground rules can be presented. The heading in the screenshot says ‘Heads-up!’ and below, a few rules are listed: ‘This is an experiment, so any feedback is welcomed afterward. - We will work together but alone. - Be patient; it’s going to be amazing once you see the results. - Our time is limited, and to keep this session efficient, let’s try to keep all our work within the timeframe.’
An example of setting the stage with some ground rules and instructions. (Large preview)

It’s important to let participants know that every workshop has its “highs” and “lows.” Make it clear at the outset that these fluctuations in pace and energy are normal and are part of the process. Encourage participants to be patient and stay engaged through the lows, as these can often lead to breakthroughs and moments of high productivity later, during the highs.

A screenshot of how AJ&Smart presents the highs and lows of the workshop process. The headline on the screenshot reads ‘Trust the Process!’, with a graph below and the words ‘start’ and ‘finish’ on the leftmost and rightmost sides; a winding line connects ‘start’ and ‘finish’
How AJ&Smart presents workshop’s highs and lows during the introduction of a workshop. (Large preview)

Step 2. Observe The Participants #

As a facilitator, it’s essential for you to observe and understand the dynamics of the group — to ensure everyone is engaged and participating effectively. Below, I’ve outlined a simpler approach to participant observation that involves looking for non-verbal cues, tracking participation levels, and paying attention to reactions to the content.

Here are a few things you should be paying attention to:

  • Non-verbal cues
    Non-verbal cues can be quite telling and often communicate more than words. Pay attention to participants’ body language as captured by their cameras, such as their posture, facial expressions, and eye contact. This also applies to in-person workshops where it is, in fact, much easier to keep track of the body language of participants. For instance, leaning back or crossing arms might suggest disengagement, while constant eye contact and active note-taking might indicate interest and engagement. When you’re facilitating a remote workshop (and there is no video connection, so you won’t have access to the usual body language indicators), pay attention to the use of emojis, reactions, and the frequency of chat activity. Also, look for signals that people want to speak; they might be unmuting themselves, using the “raise hand” button, or physically raising their hands.
  • Participation levels
    Keep track of how often and who is contributing to the discussion. If you notice a participant hasn’t contributed in a while, you might want to encourage them to share their thoughts. You could ask, “We haven’t heard from you yet. Would you like to add something to the discussion?”. Conversely, if someone seems to be dominating the conversation, you could say, “Let’s hear from someone who hasn’t had a chance to speak yet.” It’s all about ensuring a balanced participation where every voice is heard.
  • Reactions to content
    Observe participants’ reactions to the topics which are being discussed. Nods of agreement, looks of surprise, or expressions of confusion can all be very revealing. If you notice a reaction that suggests confusion or disagreement, don’t hesitate to pause and address it. You could ask the participant to share their thoughts or provide further explanations to clarify any possible misunderstandings.
  • Managing conflict
    At times, disagreements or conflicts may arise during the workshop. As a facilitator, it’s your role to manage these situations and ensure a safe and respectful environment. If a conflict arises, acknowledge it openly and encourage constructive dialogue. Remind participants of the ground rules, focusing on the importance of respecting each others’ opinions and perspectives. If necessary, you could use conflict resolution techniques, such as active listening and meditating or even taking a short break to cool down the tension.

Another helpful tip is to have a space for extra ideas. This could be a whiteboard in a physical setting or a shared digital document in a virtual one. Encourage participants to write down any thoughts or ideas that come up, even if they are not immediately relevant to the current discussion. These can be revisited later and may spur new insights or discussions.

A screenshot of the parking lot template on Miro. In the center is a large ‘P’ (Parking) sign. On the left, there are yellow notes with the heading ‘Open questions’ on top and below, ‘How will we make sure all the parked questions get addressed?’, ‘Is there a way to categorize or prioritize the questions and ideas in the Parking Lot?’ ‘How can we encourage shy participants to contribute to the Parking Lot?’. On the right, the heading is ‘Ideas to discuss’ and below, ‘Randomly pick a parked question or idea at the end of the workshop and award a small prize to the participant who posted it,’ ‘Allow participants to vote on which questions or concepts they find most relevant,’ ‘Use the Parking Lot as a way to track which concerns have been addressed over a series of workshops’
Having a “parking lot” section in your whiteboard tool allows the team to move forward while not ignoring people’s ideas. Find more about the Parking Lot template from The Facilitator’s School. (Large preview)

Another tip is to use workshop-specific tools such as Butter, where participants can express their emotions through the emoji reaction features and be queued to ask their questions without interrupting the speakers. Lastly, if you have a group larger than 5-6 people, consider dividing them into sub-groups and using co-facilitators to assist in managing these sub-groups. This will make the workshop experience much better for individual participants.

Observing others through laptop cameras can be difficult when there are more than 5-6 people in the virtual room. That’s a big reason why you’ll need to set the stage and establish a few ground rules at the beginning. Rules such as “Speak one person at a time,” “Use the ‘Raise Hand’ button to speak,” and “Leave questions in the chat space” can really improve the experience.

Remote workshops might not be able to replace the full experience of in-person workshops, where we can clearly see people’s body language and interact with each other more easily. However, with the right combination of tools and facilitation tips, remote workshops can probably match very closely the in-person experience and make the participants happy.

Step 3. Respect Your Schedule #

As you go about your workshop, respecting your agenda is essential. This is all about sticking to your plan, staying on track, and communicating clearly with the participants about what stage you’re at and what’s coming next.

Scheduled breaks are equally as important. Let’s say you’ve planned for a 10-minute break every 45 minutes, then stick to this plan. It offers participants time to rest, grab a quick snack (or coffee/tea), refresh their minds, and prepare for the next part. This is particularly significant during online workshops where screen fatigue is a common problem.

We know workshops don’t always go as planned — disruptions are often part of the package. These could range from a technical glitch during a virtual workshop, a sudden question sparking a lengthy discussion, or just starting a bit late due to late arrivals. This is where your “buffer time” will come in handy!

Respecting the buffer time allows you to handle any disruption that may come up without compromising on the workshop content or rushing through sections to recover the lost time. If there are no disruptions, this time can be used for additional discussions or exercises or even finishing the workshop earlier — something that participants usually appreciate.

Remember to stay focused. As the facilitator, you should keep discussions on track and aligned with the workshop’s goals. If the conversation veers off-topic, gently guide it back to the main point.

Applying The P.A.R.T.S. Principle: After The Workshop #

Step 1. Follow Up #

A critical part of concluding your workshop is following up with participants. This not only helps solidify the decisions and actions that were agreed upon but also maintains the collaborative momentum even after the workshop ends.

  • Meeting Minutes
    Send out a concise summary of the workshop, including the key points of discussion, decisions made, and next steps. This serves as a reference document for participants and ensures everyone is on the same page.
  • Action Plan
    Detail the agreed-upon action items, the person responsible for each, and the deadlines. This provides clarity on the tasks to be accomplished post-workshop.
  • Next Steps
    Clearly communicate the next steps, whether that’s a follow-up meeting, a deadline for tasks, or further resources to explore. This ensures that the momentum from the workshop continues.

Step 2. Celebrate #

Completing a workshop is no small feat. It takes dedication, focus, and collaborative effort from all participants. So, don’t let this moment pass uncelebrated. Recognizing everyone’s contributions and celebrating the completion of the workshop is an essential concluding step.

This not only serves as a token of gratitude for the participant’s time and effort but also reinforces the sense of achievement, promoting a positive and inclusive culture. Reflect on the journey you all undertook together, emphasizing the progress made, the skills developed, and the insights gained.

In your closing remarks or a follow-up communication, highlight specific achievements or breakthrough moments from the workshop. You might also share key takeaways or outcomes that align with the workshop’s objectives. This helps to not only recap the learning but also underscore the value each participant brought to the workshop.

Consider personalized gestures to commemorate the workshop — certificates of completion, digital badges, or even just a special mention can make participants feel recognized and appreciated. Celebrations, no matter how small, can build camaraderie, boost morale, and leave everyone looking forward to the next workshop.

Conclusion #

Let me conclude Part 2 by quoting Simon Raybould, who wonderfully encapsulates the art of facilitation, by saying:

“The secret of facilitating is to make it easy for people to learn. If you’re not making it easy, you’re not doing it right.”
— Simon Raybould

I couldn’t agree more. The inclusive workshop is not just about getting things done; it represents the symphony of diverse voices coming together, the exploration of ideas, and the collective journey toward shared objectives. Embracing this essence of inclusivity and embedding it into your workshop design and delivery makes for an environment where everyone feels respected, collaboration is enhanced, and innovative thinking flourishes.

As a facilitator, you have the power to make the workshop experience memorable and inspiring. The influence of your efforts can extend beyond the workshop, cultivating an atmosphere of respect, diversity, and inclusivity that spills over into all collaborative activities. This is the true impact and potential of well-executed, inclusive workshops.

Further Reading & References #

Here are a few additional resources on the topic of workshops. I hope you will find something useful there, too.

  • Gamestorming: A Playbook for Innovators, Rulebreakers, and Changemakers, by Dave Gray, Sunni Brown, and James Macanufo
    This well-known playbook provides a wide range of strategies and activities for designing workshops that encourage a creative, productive thinking environment. If you’re leading workshops and wish to encourage more out-of-the-box thinking, this book is a perfect source of inspiration.
  • Sprint, by Jake Knapp, John Zeratsky, and Braden Kowitz
    This is another well-known book in the workshop space. The book focuses on mastering the facilitation of Design Sprint, a workshop method by Google aimed at solving business problems and fostering collaboration. If you’re keen on leading tech teams or startups, this book is a great pick.
  • The Workshop Survival Guide, by Devin Hunt and Rob Fitzpatrick
    This guide navigates you through the end-to-end process of designing and conducting successful workshops. Whether you’re a newbie or an experienced facilitator, this resource gives comprehensive support to facilitate workshops confidently.
  • Invent To Learn: Making, Tinkering, and Engineering in the Classroom, by Sylvia Libow Martinez and Gary S. Stager
    Even though it is primarily for school educators, the book shares a wide range of methods and techniques that you can adapt to any workshop setting to create inclusive, creative, and hands-on learning environments. Highly recommended for those interested in creating an inclusive environment in any setting.
  • No Hard Feelings: The Secret Power of Embracing Emotions at Work, by Liz Fosslien and Mollie West Duffy
    Although it doesn’t focus on workshops specifically, the book gives useful insights on managing emotions at work from both participant and facilitator perspectives. It offers a broad overview of different personalities at work and how to foster emotional inclusivity, which can be valuable when facilitating workshops.
  • A Comprehensive Checklist For Running Design Workshops,” by Slava Shestopalov
    Slava’s article is a thorough guide to designing and conducting a successful workshop. This is a highly recommended read for designers, product managers, or even engineers looking to understand the nuances of running a design-centric workshop.
  • The Workshopper Playbook — A Summary” (AJ&Smart)
    The summary of “The Workshop Playbook” discusses the 4C technique that AJ&Smart developed for constructing any workshop. The 4C’s — Collect, Choose, Create, and Commit — form an exceptional workshop framework that adheres to the double-diamond method of workshop creation. If you’re interested in gaining a more profound understanding of the 4C framework, consider reading the full book by AJ&Smart.
  • The Secret To Healthy Remote Work: Fewer Meetings, More Workshops,” by Mehdi En-Naizi
    The article promotes the shift from traditional meetings to workshops in remote work settings to boost productivity and decrease stress. It highlights the workshops’ effectiveness, enhanced focus, and their role in promoting team unity and social interactions.
  • 10 Tips On Running An Online Meeting Your Team Won’t Hate (And Free Templates To Try!),” Anamaria Dorgo and Cheska Teresa
    This guide provides a detailed approach to overcoming the fatigue and frustration often associated with online meetings. The tips include clearly defining the meeting’s purpose, sticking to an agenda, creating an inclusive space for active participation, scheduling regular breaks, and using breakout rooms for more focused discussions.
  • How Silent Brainstorming Easily Engages Introverts On The Project Team,” by Annie MacLeod (DPM)
    Try out this brainstorming technique next time you need to get the team’s input on a problem or solution or if you’re working on a team with a lot of introverts.
  • Dot Voting: A Simple Decision-Making and Prioritizing Technique in UX,” Sarah Gibbons (NN/g Nielsen Norman Group)
    A few UX workshop activities work well in any situation, and dot voting is one of them. Dot voting is a simple tool used to democratically prioritize items or make decisions in a group setting. It is an easy, straightforward way to narrow down alternatives and converge on a set of concepts or ideas.
  • How Do You Encourage Introverts And Quiet Participants To Share Their Ideas In A Meeting?” (LinkedIn — Meeting Facilitation)
    Meetings are essential for collaboration, creativity, and innovation. But not everyone feels comfortable speaking up in a group setting. Some people may be introverted, shy, or simply prefer to listen and process information before sharing their thoughts. How do you encourage these quiet participants to contribute their valuable ideas in a meeting?
  • Teacher Toolkit: Think-Pair-Share” — YouTube, (Think-Pair-Share webpage)
    This versatile tool can be used in any classroom. The discussion technique gives students the opportunity to respond to questions in written form before engaging in meaningful conversation with other students. Asking students to write and discuss ideas with a partner before sharing with the larger group builds confidence, encourages greater participation, and results in more thoughtful discussions.
    (Editor’s Note: The Teacher Toolkit webpage is temporarily down. Until their server is restored, you can use a full webpage copy preserved by the WayBack Machine. — MB)
  • Fishbowl Conversation
    Fishbowl Conversation is great for keeping a focused conversation when you have a large group of people. At any time, only a few people have a conversation (the fish in the fishbowl). The remaining people are listeners (the ones watching the fishbowl). The caveat is that the listeners can join the discussion at any moment.
  • Lightning Talks” (Design sprints by Google)
    Lightning Talks are a core Design Sprint method and a powerful opportunity to build ownership in the Design Sprint challenge. Plan and set up Lightning Talks before your Design Sprint begins. After all the Lightning Talks are finished, hold an HMW sharing session to capture and share all the opportunities your team has come up with.
  • AJ&Smart’s Remote Design Sprint
    The lightning demo activity from Design Sprint is a perfect example of the “Idea Gallery” type of activity. Participants work individually to create a visual or written representation of their ideas (like a poster), and then everyone walks around to view the “gallery” and people discuss the ideas.
  • Poster Session” (Gamestorming)
    The goal of a poster session is to create a set of compelling images that summarize a challenge or topic for further discussion. Creating this set might be an “opening act,” which then sets the stage for choosing an idea to pursue, or it might be a way to get indexed on a large topic.
  • Jigsaw Activities” (The Bell Foundation)
    Jigsaw activities are a specific type of information gap activity that works best when used with the whole class. The class is first divided into groups of four to six learners who are then given some information on a particular aspect of the topic, which they later become experts in.
  • Disney Brainstorming Method
    The Disney method was developed in 1994 by Robert Dilts based on Walt Disney’s creative approach. It’s a good mix of creativity and concreteness as it’s not only about generating ideas but also looking at them with a critical eye and, eventually, having a few of them ready to be further explored and implemented.
  • Support Extroverted Students in Remote Environment — Group Discussions
    Several video platforms have options for small group discussions. If you’re using one of these, breaking into small groups can be a great opportunity to help your extroverted students feel fulfilled (and for your more introverted students to “warm up” for group discussion).
  • 37 brainstorming techniques to unlock team creativity,” by James Smart (SessionLab)
    It’s important to find a framework and idea-generation process that empowers your group to generate meaningful results, as finding new and innovative ideas is a vital part of the growth and success of any team or organization. In this article, several effective brainstorming techniques are explored in detail in categories such as creative exercises and visual idea-generation games.
  • Round-Robin Brainstorming” (MindTools blog)
    It’s all too easy to start a brainstorming session with good intentions but then overlook or miss potentially great ideas simply because one assertive person sets the tone for the entire meeting. This is why a tool like Round-Robin Brainstorming is so valuable. This method allows team members to generate ideas without being influenced by any one person, and you can then take these ideas into the next stages of the problem-solving process.
  • Eysenck’s Personality Theory” (TutorialsPoint)
    What is Eysenck’s Personality Theory? This theory has been influential in personality psychology and used to explain various phenomena, including individual differences in behavior and mental health.
  • Meeting Design: For Managers, Makers, and Everyone, a book by Kevin Hoffman
    Meetings don’t have to be painfully inefficient “snoozefests” — if you design them well. Meeting Design will teach you the design principles and innovative approaches you’ll need to transform meetings from boring to creative, from wasteful to productive.
  • State of Meetings Report 2021
    How did meetings actually change in 2020? What will the long-term impact of this change be? And could 2020 have changed the way we meet for good? These are questions that will be answered in this detailed report.
  • Social Identity Theory (Science Direct)
    Social identity theory defines a group as a collection of people who categorize themselves as belonging to the same social category and internalize the category’s social identity-defining attributes to define and evaluate themselves — attributes that capture and accentuate intragroup similarities and intergroup differences.
  • Clarizen Survey Pins Falling Productivity Levels on Communication Overload” (Bloomberg)
    A new survey by Clarizen, the global leader in collaborative work management, finds that companies’ efforts to improve collaboration among employees by opening new lines of communication can have the opposite effect.
  • Conflict Resolution Skills: What They Are and How to Use Them” (Coursera)
    Handling conflict in any context is never fun. Often, issues become more complicated than needed if the people involved need more conflict resolution and general communication skills. In this article, you’ll learn more about conflict resolution and, more specifically, how different conflict resolution skills may be useful in various situations.
  • Meeting Parking Lot” (The Facilitator’s School)
    A free template for handling off-topic questions, topics, and discussions. Available in Miro Template and Mural Template format.
  • SmashingConf Online Workshops
    Finally, do meet the friendly Smashing Magazine front-end & UX workshops! These remote workshops aim to give the same experience and access to experts that you would have in an in-person workshop without needing to leave your desk or couch. You can follow along with practical examples and interactive exercises, ask questions during the Q&A sessions, and use workshop recordings and materials to study at your own pace, at your own time.

The Path To Awesome CSS Easing With The linear() Function

 With the new CSS linear() easing function on the horizon, the possibilities of what we can do to create natural-feeling animations and transitions in the future are greatly expanded. Jhey Tompkins looks at the current state of CSS easing in this article and demonstrates what we can expect from linear(), including handy tools to get your hands on it today.

To paraphrase a saying that has always stuck with me: “The best animation is that which goes unnoticed.” One of the most important concepts of motion design on the web is making motion “feel right.” At the same time, CSS has been fairly limited when it comes to creating animations and transitions that feel natural and are unobtrusive to the user experience.

Fortunately, that’s changing. Today, let’s look at new easing capabilities arriving in CSS. Specifically, I want to demonstrate the easing superpowers of linear() — a new easing function that is currently defined in the CSS Easing Level 2 specification in the Editor’s Draft. Together, we’ll explore its ability to craft custom easing curves that lead to natural-feeling UI movement.

The fact that linear() is in the Editor’s Draft status means we’re diving into something still taking shape and could change by the time it reaches the Candidate Recommendation. As you might imagine, that means linear() has limited support at this moment in time. It is supported in Chrome and Firefox, however, so be sure to bear that in mind as we get into some demos.

Before we jump straight in, there are a couple of articles I recommend checking out. They’ve really influenced how I approach UI motion design as a whole:

There are plenty of great resources for designing motion in UI, but those are two that I always keep within reach in my browser’s bookmarks, and they have certainly influenced this article.

The Current State Of Easing In CSS #

We define CSS easing with either the animation-timing-function or transition-timing-function properties, depending on whether we are working with an animation or transition respectively.

Duration is all about timing, and timing has a big impact on the movement’s naturalness.

But, until recently, CSS has limited us to the following easing functions:

  • linear,
  • steps,
  • ease,
  • ease-in,
  • ease-out,
  • ease-in-out,
  • cubic-bezier().

For a refresher, check out this demo that shows the effect of different timings on how this car travels down the track.

See the Pen Traditional CSS Easing Options [forked] by Jhey.

The cubic-bezier() function has traditionally provided the most flexibility for creating easing with a little character. The site cubic-bezier.com is a great resource for creating bespoke easing functions. Otherwise, figuring out the exact curve values can be a chore.

This is the current state of easing in CSS. We’ll get to the shiny, new stuff in a bit. But first, I think it’s a good idea to revisit how easing functions influence easing behavior in curvatures.

Visualizing Easing Curves #

We can visualize different easings with a graphical curve. The site easings.net does a good job of providing options that can be used with the cubic-bezier() timing function.

Easing curves which represent movement’s behavior
An easing curve represents the movement’s behavior. The left end is the start of the movement, and the segments in blue represent faster movement. (Large preview)

Easing curves can also be viewed in Chromium DevTools, allowing you to inspect any curve applied to a transition or animation.

A screenshot showing how to edit the curves
The curves are directly editable with the toggles on each endpoint. (Large preview)

Getting “Extra” Easing With linear() #

But what if you need something a little extra than what’s available? For example, what about a bounce? Or a spring? These are the types of easing functions that we are unable to achieve with a cubic-bezier() curve.

This is where the new linear() easing function comes into play, pioneered by Jake Archibald and defined in the CSS Easing Level 2 specification, which is currently in the Editor’s Draft. MDN describes it well:

The linear() function defines a piecewise linear function that interpolates linearly between its points, allowing you to approximate more complex animations like bounce and elastic effects.

In other words, it’s a way to plot a graph with as many points as you like to define a custom easing curve. That’s pretty special and opens new possibilities we could not do before with CSS animations and transitions.

For example, the easing for a bounce could look like this:

:root {
  --bounce-easing: linear(
    0, 0.004, 0.016, 0.035, 0.063, 0.098, 0.141 13.6%, 0.25, 0.391, 0.563, 0.765,
    1, 0.891 40.9%, 0.848, 0.813, 0.785, 0.766, 0.754, 0.75, 0.754, 0.766, 0.785,
    0.813, 0.848, 0.891 68.2%, 1 72.7%, 0.973, 0.953, 0.941, 0.938, 0.941, 0.953,
    0.973, 1, 0.988, 0.984, 0.988, 1
  );
}

Here’s how that looks in action:

See the Pen Bounce Easing 🏀 [forked] by Jhey.

A gentle reminder that browser support is limited to Chrome and Firefox, so be sure to view the demo in one of those browsers. We’re only waiting on Safari at the moment, so we’re almost there!

“I’m not working all that out.” #

That easing example sure looks like a lot of numbers plucked straight out of thin air, doesn’t it? As far as complexity goes, we’re looking at something that’s as scary as cubic-bezier() at first glance. The good thing is, once you’ve defined an ease, you’re unlikely to have to touch it again… at least for a while. It’s pretty much a set-it-and-forget-it sort of thing.

But how do we get the numbers in the first place? Jake, the clever mind behind linear(), put together an online generator that does all the heavy lifting for us. In fact, I got the easing values for the bounce demo straight from Jake’s handy tool. Here is a permalink to the output.

linear() generator app
linear() generator app. (Large preview)

Where’s All Of This Going? #

For as long as I can remember, if I’ve needed some special easing for the work I’m doing, GreenSock has been my go-to solution. Its ease visualizer is one of my favorite examples of interactive documentation.

GreenSock’s Ease Visualizer which demonstrates different easing curves
GreenSock’s Ease Visualizer demonstrates different easing curves — including custom curves — and provides a snippet to use with its library. (Large preview)

As soon as I heard about the linear() function, my mind went straight to: “How can I convert GreenSock eases to CSS?” Imagine how awesome it would be to have access to a popular set of eases that can be used directly in CSS without reaching for JavaScript.

GreenSock’s visualizer accepts JavaScript or an SVG path. So, my first thought was to open DevTools, grab the SVG paths from the visualizer, and drop them into the tool. However, I encountered a hurdle because I needed to scale down the path coordinates for a viewBox of 0 0 1 1. GreenSock’s visualizer has a viewBox set to 0 0 500 500. I wrote a function to convert the coordinates and reverse the path to go in the right direction. Then, I reached out to Jake with some questions about the generator. The code is available on GitHub.

In my head, I thought the SVG route made sense. But, then I created a path that wouldn’t work in the tool. So, I reached back out to Jake, and we both thought the issue was a bug in the tool.

Jake then asked, “Why do you need to go via SVG?”. His question was spot on! The JavaScript input for the tool expects an easing function. An easing function maps time to a progress value. And we can get the easing functions straight out of GreenSock and pass them to the generator. Jake managed to dig the back easing function out of the GreenSock GitHub repo and create the easing I was originally after.

Generating GSAP Eases For CSS #

Now that I’ve given you a bunch of context, we have all the parts of the puzzle we need to make something that can convert GSAP easing to CSS code.

First, we extract the parts from Jake’s linear() generator tool into a script. The idea is to loop over a set of keys and generate a block of CSS with linear() easings. GreenSock has a lovely utility method called parseEase. It takes a string and returns the easing function. The accepted strings are the GreenSock easing functions.

const ease = gsap.parseEase('power1.in')
ease(0.5) // === 0.25

As this loops over an object with different easing functions, we can pass them into the extracted code from the tool. We modify that extracted code to our needs.

const easings = ''
const simplified = 0.0025
const rounded = 4
const EASES = {
  'power-1--out': gsap.parseEase('power1.out')
  // Other eases
}
// Loop over the easing keys and generate results.
for (const key of Object.keys(EASES)) {
  // Pass the easing function through the linear-generator code.
  const result = processEase(key, EASES[key])
  const optimised = useOptimizedPoints(result.points, simplified, rounded)
  const linear = useLinearSyntax(optimised, rounded)
  const output = useFriendlyLinearCode(linear, result.name, 0)
  easings += output
}
// Generate an output CSS string.
let outputStart = ':root {'
let outputEnd = '}' 
let styles = `
  ${outputStart}
  ${easings}
  ${outputEnd}
`
// Write it to the body.
document.body.innerHTML = styles

The functions we extracted from the linear generator do different things:

  • processEase
    This is a modified version of processScriptData. It takes the easing functions and returns points for our graph.
  • useOptimizedPoints
    This optimizes those points based on the simplied and rounded values. This was where I learned about the Douglas Peucker algorithm from Jake.
  • useLinearSyntax
    This takes the optimized points and returns the values for the linear() function.
  • useFriendlyLinearCode
    This takes the linear values and returns a CSS string that we can use with the ease’s custom property name.

It’s worth noting that I’ve tried not to touch these too much. But it’s also worth digging in and dropping in a breakpoint or console.info at various spots to understand how things are working.

After running things, the result gives us CSS variables containing the linear() easing functions and values. The following example shows the elastic and bounce eases.

:root {
  --elastic-in: linear( 0, 0.0019 13.34%, -0.0056 27.76%, -0.0012 31.86%, 0.0147 39.29%, 0.0161 42.46%, 0.0039 46.74%, -0.0416 54.3%, -0.046 57.29%, -0.0357, -0.0122 61.67%, 0.1176 69.29%, 0.1302 70.79%, 0.1306 72.16%, 0.1088 74.09%, 0.059 75.99%, -0.0317 78.19%, -0.3151 83.8%, -0.3643 85.52%, -0.3726, -0.3705 87.06%, -0.3463, -0.2959 89.3%, -0.1144 91.51%, 0.7822 97.9%, 1 );
  --elastic-out: linear( 0, 0.2178 2.1%, 1.1144 8.49%, 1.2959 10.7%, 1.3463 11.81%, 1.3705 12.94%, 1.3726, 1.3643 14.48%, 1.3151 16.2%, 1.0317 21.81%, 0.941 24.01%, 0.8912 25.91%, 0.8694 27.84%, 0.8698 29.21%, 0.8824 30.71%, 1.0122 38.33%, 1.0357, 1.046 42.71%, 1.0416 45.7%, 0.9961 53.26%, 0.9839 57.54%, 0.9853 60.71%, 1.0012 68.14%, 1.0056 72.24%, 0.9981 86.66%, 1 );
  --elastic-in-out: linear( 0, -0.0028 13.88%, 0.0081 21.23%, 0.002 23.37%, -0.0208 27.14%, -0.023 28.64%, -0.0178, -0.0061 30.83%, 0.0588 34.64%, 0.0651 35.39%, 0.0653 36.07%, 0.0514, 0.0184 38.3%, -0.1687 42.21%, -0.1857 43.04%, -0.181 43.8%, -0.1297 44.93%, -0.0201 46.08%, 1.0518 54.2%, 1.1471, 1.1853 56.48%, 1.1821 57.25%, 1.1573 58.11%, 0.9709 62%, 0.9458, 0.9347 63.92%, 0.9349 64.61%, 0.9412 65.36%, 1.0061 69.17%, 1.0178, 1.023 71.36%, 1.0208 72.86%, 0.998 76.63%, 0.9919 78.77%, 1.0028 86.12%, 1 );
    --bounce-in: linear( 0, 0.0117, 0.0156, 0.0117, 0, 0.0273, 0.0468, 0.0586, 0.0625, 0.0586, 0.0468, 0.0273, 0 27.27%, 0.1093, 0.1875 36.36%, 0.2148, 0.2343, 0.2461, 0.25, 0.2461, 0.2344, 0.2148 52.28%, 0.1875 54.55%, 0.1095, 0, 0.2341, 0.4375, 0.6092, 0.75, 0.8593, 0.9375 90.91%, 0.9648, 0.9843, 0.9961, 1 );
  --bounce-out: linear( 0, 0.0039, 0.0157, 0.0352, 0.0625 9.09%, 0.1407, 0.25, 0.3908, 0.5625, 0.7654, 1, 0.8907, 0.8125 45.45%, 0.7852, 0.7657, 0.7539, 0.75, 0.7539, 0.7657, 0.7852, 0.8125 63.64%, 0.8905, 1 72.73%, 0.9727, 0.9532, 0.9414, 0.9375, 0.9414, 0.9531, 0.9726, 1, 0.9883, 0.9844, 0.9883, 1 );
  --bounce-in-out: linear( 0, 0.0078, 0, 0.0235, 0.0313, 0.0235, 0.0001 13.63%, 0.0549 15.92%, 0.0938, 0.1172, 0.125, 0.1172, 0.0939 27.26%, 0.0554 29.51%, 0.0003 31.82%, 0.2192, 0.3751 40.91%, 0.4332, 0.4734 45.8%, 0.4947 48.12%, 0.5027 51.35%, 0.5153 53.19%, 0.5437, 0.5868 57.58%, 0.6579, 0.7504 62.87%, 0.9999 68.19%, 0.9453, 0.9061, 0.8828, 0.875, 0.8828, 0.9063, 0.9451 84.08%, 0.9999 86.37%, 0.9765, 0.9688, 0.9765, 1, 0.9922, 1 );
}

We’re able to adjust this output to our heart’s desire with different keys or accuracy. The really cool thing is that we can now drop these GreenSock eases into CSS!

How To Get Your Very Own CSS linear() Ease #

Here’s a little tool I put together. It allows you to select the type of animation you want, apply a linear() ease to it, and determine its speed. From there, flip the card over to view and copy the generated code.

See the Pen GreenSock Easing with CSS linear() ⚡️ [forked] by Jhey.

In cases where linear() isn’t supported by a browser, we could use a fallback value for the ease using @supports:

:root {
  --ease: ease-in-out;
}
@supports(animation-timing-function: linear(0, 1)) {
  :root {
    --ease: var(--bounce-easing);
  }
}

And just for fun, here’s a demo that takes the GreenSock ease string as an input and gives you the linear() function back. Try something like elastic.out(1, 0.1) and see what happens!

See the Pen Convert GSAP Ease to CSS linear() [forked] by Jhey.

Bonus: Linear Eases For Tailwind #

You don’t think we’d leave out those of you who use Tailwind, do you? Not a chance. In fact, extending Tailwind with our custom eases isn’t much trouble at all.

/** @type {import('tailwindcss').Config} */
const plugin = require('tailwindcss/plugin')
const EASES = {
  "power1-in": "linear( 0, 0.0039, 0.0156, 0.0352, 0.0625, 0.0977, 0.1407, 0.1914, 0.2499, 0.3164, 0.3906 62.5%, 0.5625, 0.7656, 1 )",
  /* Other eases */
}
const twease = plugin(
  function ({addUtilities, theme, e}) {
    const values = theme('transitionTimingFunction')
    var utilities = Object.entries(values).map(([key, value]) => {
      return {
        [`.${e(`animation-timing-${key}`)}`]: {animationTimingFunction: `${value}`},
      }
    })
    addUtilities(utilities)
  }
)
module.exports = {
  theme: {
    extend: {
      transitionTimingFunction: {
        ...EASES,
      }
    },
  },
  plugins: [twease],
}

I’ve put something together in Tailwind Play for you to see this in action and do some experimenting. This will give you classes like animation-timing-bounce-out and ease-bounce-out.

Conclusion #

CSS has traditionally only provided limited control over the timing of animations and transitions. The only way to get the behavior we wanted was to reach for JavaScript solutions. Well, that’s soon going to change, thanks to the easing superpowers of the new linear() timing function that’s defined in the CSS Easing Level 2 draft specification. Be sure to drop those transitions into your demos, and I look forward to seeing what you do with them!

Stay awesome. ┬┴┬┴┤•ᴥ•ʔ├┬┴┬┴

Revealing Images With CSS Mask Animations

 Let’s play with images and experiment with CSS masks. The idea is fairly simple: take a single <img> tag and harness the power of CSS to accomplish complex hover transitions. Through different demos, you will see how CSS masks combined with gradients allow us to create fancy effects — with efficient, reusable code.

In a previous article, we explored fancy hover effects for images that involve shines, rotations, and 3D perspectives. We are going to continue playing with images, but this time, we are making animations that reveal images on hover. Specifically, we will learn about CSS masks and how they can be used to cover portions of an image that are revealed when the cursor hovers over the image.

Here is the HTML we will use for our work:

<img src="" alt="">

Yes, that’s right, only one image tag. The challenge I like to take on with each new CSS project is: Let CSS do all of the work without extra markup.

As we go, you may notice minor differences between the code I share in the article and what is used inside the demos. The code throughout the article reflects the CSS specification. But since browser support is inconsistent with some of the features we’re using, I include prefixed properties for broader support.

Example 1: Circle Reveal #

In this first one, an image sits in a square container that is wiped away on hover to reveal the image.

See the Pen Hover reveal animation using mask by Temani Afif.

The first step for us is to create the image container and the gradient border around it. The container is actually a repeating linear gradient background set on the <img> tag. If we add a little amount of padding on the image, that allows the gradient background to show through.

img {
  padding: 10px;
  background: repeating-linear-gradient(45deg, #FF6B6B 0 10px, #4ECDC4 0 20px);
}
Two square images with striped gradient borders
Two square images with striped gradient borders. (Large preview)

So, we have two images, each with a gradient background that is revealed with a touch of padding. We could have added a <div> — or perhaps even a <figure> — to the markup to create a true container, but that goes against the challenge of letting CSS do all of the work.

While we were able to work around the need for extra markup, we now have to ask ourselves: How do we hide the image without affecting the gradient background? What we need is to hide the image but continue to show the padded area around it. Enter CSS masks.

It’s not terribly complicated to apply a mask to an element, but it’s a little trickier in this context. The “trick” is to chain two mask layers together and be more explicit about where the masks are applied:

img {
  /* etc. */
  mask:
    linear-gradient(#000 0 0) padding-box,
    linear-gradient(#000 0 0) content-box;
}

Now we have two masks “sources”:

  1. content-box: one that is restricted to the image’s content,
  2. padding-box: one that covers the whole image area, including the padded area.

We need two layers because then we can combine them with the CSS mask-composite property. We have different ways to combine mask layers with mask-composite, one of which is to “exclude” the area where the two masks overlap each other.

img {
  /* etc. */
  mask:
    linear-gradient(#000 0 0) padding-box,
    linear-gradient(#000 0 0) content-box;
  mask-composite: exclude;
}

This will make only the gradient visible (the padded area), as you can see below.

See the Pen Overview of the exclude composition by Temani Afif.

Notice that we can remove the padding-box from the code since, by default, a gradient covers the whole area, and this is what we need.

Are there other ways we could do this without mask-composite? There are many ways to hide the content box while showing only the padded area. Here is one approach using a conic-gradient as the mask:

mask:
  conic-gradient(from 90deg at 10px 10px, #0000 25%, #000 0)
  0 0 / calc(100% - 10px) calc(100% - 10px);
  /* 10px is the value of padding */
See the Pen Border-only using conic-gradient by Temani Afif.

There are others, of course, but I think you get the idea. The approach you choose is totally up to you. I personally think that using mask-composite is best since it doesn’t require us to know the padding value in advance or change it in more than one place. Plus, it’s a good chance to practice using mask-composite.

Now, let’s replace the second gradient (the one covering only the content area) with a radial-gradient. We want a circle swipe for the hover transition, after all.

img {
  mask:
    linear-gradient(#000 0 0),
    radial-gradient(#000 70%,#0000 71%) content-box;
  mask-composite: exclude;
}
See the Pen Adding the radial-gradient by Temani Afif.

See that? The exclude mask composite creates a hole in the image. Let’s play with the size and position of that cutout and see what is happening. Specifically, I’m going to cut the size in half and position the circle in the center of the image:

mask:
  linear-gradient(#000 0 0),
  radial-gradient(#000 70%,#0000 71%) content-box
    center / 50% 50% no-repeat;
  mask-composite: exclude;
See the Pen Updating the radial-gradient size and position by Temani Afif.

I bet you can already see where this is going. We adjust the size of the radial-gradient to either hide the image (increase) or reveal the image (decrease). To fully hide the image, we need to scale the mask up to such an extent that the circle covers up the image. That means we need something greater than 100%. I did some boring math and found that 141% is the precise amount, but you could wing it with a round number if you’d like.

That gives us our final CSS for the effect:

img {
  padding: 10px; /* control the thickness of the gradient "border" */
  background: repeating-linear-gradient(45deg, #FF6B6B 0 10px, #4ECDC4 0 20px);
  mask:
    linear-gradient(#000 0 0),
    radial-gradient(#000 70%, #0000 71%) content-box
      50% / var(--_s, 150% 150%) no-repeat;
  mask-composite: exclude;
  transition: .5s;
}
img:hover {
  --_s: 0% 0%;
}

A few minor details:

  • We start with a size equal to 150% 150% to initially hide the image. I am taking the additional step of applying the size as a CSS variable (--_s) with the full size (150% 150%) as a fallback value. This way, all we need to do is update the variable on hover.
  • Add a hover state that decreases the size to zero so that the image is fully revealed.
  • Apply a slight transition of .5s to smooth out the hover effect.

Here’s the final demo one more time:

See the Pen Hover reveal animation using mask by Temani Afif.

We just created a nice reveal animation with only a few lines of CSS — and no additional markup! We didn’t even need to resort to pseudo-elements. And this is merely one way to configure things. For example, we could play with the mask’s position to create a slick variation of the effect:

See the Pen Another variation of the circular reveal animation by Temani Afif.

I’m a big fan of putting an idea out there and pushing it forward with more experiments. Fork the demo and let me know what interesting things you can make out of it!

Example 2: Diagonal Reveal #

Let’s increase the difficulty and try to create a hover effect that needs three gradients instead of two.

See the Pen Hover reveal animation using mask II by Temani Afif.

Don’t look at the code just yet. Let’s try to create it step-by-step, starting with a simpler effect that follows the same pattern we created in the first example. The difference is that we’re swapping the radial-gradient with a linear-gradient:

img {
  padding: 10px; /* control the thickness of the gradient "border" */
  background: repeating-linear-gradient(45deg, #FF6B6B 0 10px, #4ECDC4 0 20px);
  mask:
    linear-gradient(#000 0 0),
    linear-gradient(135deg, #000 50%, #0000 0) content-box 
      0% 0% / 200% 200% no-repeat;
  mask-composite: exclude;
  transition: .5s;
}
img:hover {
  mask-position: 100% 100%;
    }

You’ll notice that the other minor difference between this CSS and the first example is that the size of the mask is equal to 200% 200%. Also, this time, the mask’s position is updated on hover instead of its size, going from 0% 0% (top-left) to 100% 100% (bottom-right) to create a swiping effect.

See the Pen Diagonal reveal animation using mask by Temani Afif.

We can change the swipe direction merely by reversing the linear gradient angle from 135deg to -45deg, then updating the position to 0% 0% on hover instead of 100% 100%:

img {
  padding: 10px; /* control the thickness of the gradient "border" */
  background: repeating-linear-gradient(45deg, #FF6B6B 0 10px, #4ECDC4 0 20px);
  mask:
    linear-gradient(#000 0 0),
    linear-gradient(-45deg, #000 50%, #0000 0) content-box 
      100% 100% / 200% 200% no-repeat;
  mask-composite: exclude;
  transition: .5s;
}
img:hover {
  mask-position: 0% 0%;
}
See the Pen Diagonal reveal animation using mask by Temani Afif.

One more thing: I defined only one mask-position value on hover, but we have two gradients. If you’re wondering how that works, the mask’s position applies to the first gradient, but since a gradient occupies the full area it is applied to, it cannot be moved with percentage values. That means we can safely define only one value for both gradients, and it will affect only the second gradient. I explain this idea much more thoroughly in this Stack Overflow answer. The answer discusses background-position, but the same logic applies to mask-position.

Next, I’d like to try to combine the last two effects we created. Check the demo below to understand how I want the combination to work:

See the Pen Combination of two diagonal reveal by Temani Afif.

This time, both gradients start at the center (50% 50%). The first gradient hides the top-left part of the image, while the second gradient hides the bottom-right part of it. On hover, both gradients slide in the opposite direction to reveal the full image.

If you’re like me, you’re probably thinking: Add all the gradients together, and we’re done. Yes, that is the most intuitive solution, and it would look like this:

img {
  padding: 10px; /* control the thickness of the gradient "border" */
  background: repeating-linear-gradient(45deg, #FF6B6B 0 10px, #4ECDC4 0 20px);
  mask:
    linear-gradient(#000 0 0),
    linear-gradient(135deg, #000 50%, #0000 0) content-box 
      50% 50% / 200% 200% no-repeat,
    linear-gradient(-45deg, #000 50%, #0000 0) content-box 
      50% 50 / 200% 200% no-repeat;
  mask-composite: exclude;
  transition: .5s;
  cursor: pointer;
}
img:hover {
  mask-position: 0% 0%, 100% 100%;
}
See the Pen Combining both effects by Temani Afif.

This approach kind of works, but we have a small visual glitch. Notice how a strange diagonal line is visible due to the nature of gradients and issues with anti-aliasing. We can try to fix this by increasing the percentage slightly to 50.5% instead of 50%:

See the Pen Trying to fix the anti-aliasing issue by Temani Afif.

Yikes, that makes it even worse. You are probably wondering if I should decrease the percentage instead of increasing it. Try it, and the same thing happens.

The fix is to update the mask-composite property. If you recall, we are already using the exclude value. Instead of declaring exclude alone, we need to also apply the add value to make sure the bottom layers (the swiping gradients) aren’t excluded from each other but are instead added together:

img {
  mask:
    /* 1st layer */
    linear-gradient(#000 0 0),

    /* 2nd layer */
    linear-gradient(135deg, #000 50.5%, #0000 0) content-box 
      50% 50% / 200% 200% no-repeat,

    /* 3rd layer */
    linear-gradient(-45deg, #000 50.5%, #0000 0) content-box 
      50% 50% / 200% 200% no-repeat;

  mask-composite: exclude, add;
}

Now, the second and third layers will use the add composition to create an intermediate layer that will be excluded from the first one. In other words, we must exclude all the layers from the first one.

I know mask-composite is a convoluted concept. I highly recommend you read Ana Tudor’s crash course on mask composition for a deeper and more thorough explanation of how the mask-composite property works with multiple layers.

This fixes the line issue in our hover effect:

See the Pen Diagonal reveal animation using mask by Temani Afif.

One more small detail you may have spotted: we have defined three gradients in the code but only two mask-position values on the hover state:

img:hover {
  mask-position: 0% 0%, 100% 100%;
}

The first value (0% 0%) is applied to the first gradient layer; it won’t move as it did before. The second value (100% 100%) is applied to the second gradient layer. Meanwhile, the third gradient layer uses the first value! When fewer values are declared on mask-position than the number of mask layers, the series of comma-separated values repeats until all of the mask layers are accounted for.

In this case, the series repeats circles back to the first value (0% 0%) to ensure the third mask layer takes a value. So, really, the code above is a more succinct equivalent to writing this:

img:hover {
  mask-position: 0% 0%, 100% 100%, 0% 0%;
}

Here is the final demo again with both variations. You will see that the second example uses the same code with minor updates.

See the Pen Hover reveal animation using mask II by Temani Afif.

Example 3: Zig-Zag Reveal #

I have one more example for you, this time revealing the image with zig-zag edges sliding apart, sort of like teeth chomping on the image.

See the Pen Hover reveal animation using mask III by Temani Afif.

While this may look like a more complex hover effect than the last two we covered, it still uses the same underlying CSS pattern we’ve used all along. In fact, I’m not even going to dive into the code as I want you to reverse-engineer it using what you now know about using CSS gradients as masks and combining mask layers with mask-composite.

I won’t give you the answer, but I will share an article I wrote that demonstrates how I created the zig-zag shape. And since I’m feeling generous, I’ll link up this online border generator as another resource.

Wrapping Up #

I hope you enjoyed this little experiment with CSS masks and gradients! Gradients can be confusing, but mixing them with masks is nothing short of complicated. But after spending the time it takes to look at three examples in pieces, we can clearly see how gradients can be used as masks as well as how we can combine them to “draw” visible areas.

Once we have an idea of how that works, it’s amazing that all we need to do to get the effect is update either the mask’s position or size on the element’s hover state. And the fact that we can accomplish all of this with a single HTML element shows just how powerful CSS is.

We saw how the same general CSS pattern can be tweaked to generate countless variations of the same effect. I thought I’d end this article with a few more examples for you to play with.

See the Pen Hover reveal animation using mask IV by Temani Afif.
See the Pen Hover reveal animation using mask V by Temani Afif.
See the Pen Hover reveal animation using mask VI by Temani Afif.