Podcasts For UX Designers

What UX podcasts are you listening to? Below you’ll find a few wonderful UX podcasts we came across, as well as podcasts that the UX community shared with us.

Whether you’re particularly interested in user research, are looking for advice to navigate a career in UX, or want to better understand how the human brain works, the podcasts in this collection cover every possible aspect of UX. Not all of them are still running, but the archives are incredible, with interviews full of insights and gems.

A huge thank-you to the hosts — and, of course, the people behind the scenes — for producing these podcasts and helping us all make sense of the multifaceted, exciting world that UX is.

So, prepare yourself a nice cup of coffee and get cozy — oh, and don’t forget to charge your headphones before your next commute. Happy listening!

Table Of Contents

You can jump directly to the topic you’re interested in to find podcasts relevant to you or browse through the complete list.

UX Tips And Best Practices

UX Cake

UX Cake helps you become more effective in your UX work and career. In each episode, host Leigh Allen-Arredondo invites leaders in the field of UX to share their practical advice to get the best outcomes for your work, your users, and your career in UX.

The NN/g UX Podcast

In the Nielsen Norman Group UX Podcast, Senior User Experience Specialist Therese Fessenden interviews industry experts, covering common questions, hot takes on pressing UX topics, and tips for building truly great user experiences.

User Defenders

Helping you to better fight for your users and business is the mission of the User Defenders podcast. In every episode, influential UX superheros share their stories, reveal their design superpowers, and offer their advice.

24 Minutes Of UX

Every 24 Minutes of UX episode features a curious “Seeker” who is seeking advice in a specific topic within the domain of UX and an experienced “Giver” who shares the knowledge they gathered around the topic over the years.

Boagworld Show

The Boagworld Show was the first web design podcast and ran from 2005 to 2021, interviewing the leading minds in the field and sharing best practices in digital. The archive is a treasure chest for any UX professional.

User Research

Awkward Silences

Awkward Silences interviews the people who interview people. The podcast dives deep into all things UX research, qualitative data, and the craft of understanding people to build better products and businesses.

UX Research Geeks

UX Research Geeks is all about User Experience Design, research, and everything that goes along with it. Among the guests are senior researchers, designers, speakers, CEOs, startup founders, and many more.

Human Behavior

Hidden Brain

In Hidden Brain, Shankar Vedantam uses science and storytelling to reveal the unconscious patterns that drive human behavior, shape our choices, and direct our relationships.

The Cognitive Bias

Clear language, the value of discomfort, and the psychology of money are just a few of the topics that The Cognitive Bias covers. It explores the world of things we do that don’t make any rational sense, one bias at a time.

Human-Centered Design

This Is HCD — Human-Centered Design Podcast

The mission of the Human Centered Design Podcast is to educate and empower people and organizations about the power of true human-centered design. It brings together thought leaders from various disciplines such as service design, user experience, interaction design, and product management to better understand what it means to work within a human-centric method.

  • 🎙 Hosted by This is HCD
  • 🗓 Several episodes per month



UXpod offers a free-ranging set of discussions around UX design, website design, and usability in general. The podcast retired last year, but there is an incredible archive with more than 120 episodes and even transcripts.


A11y Rules

There is a lot of information about making the web accessible, but not so much information about the people working to make the web accessible. A11y Podcast is here to change that by inviting people involved with web accessibility.


UI Breakfast Podcast

In the UI Breakfast Podcast, Jane Portman invites industry experts to share actionable knowledge. The topics cover UI/UX design, products, marketing, and more.

UX Systems

The Object-Oriented UX Podcast

The Object-Oriented UX Podcast is a deep-dive into the weeds of UX systems, information architecture, human psychology, data wrangling, structured content, UX process, and, above all, simplifying the complex.

Content Strategy

The Content Strategy Podcast

The Content Strategy Podcast is a show for people who care about all things content. Kristina Halvorson interviews expert leaders and exciting new voices in the field of content strategy, diving deep into topics that inform how we shape digital content and how it, in turn, shapes us.

Writers In Tech

Brought to you by the UX Writing Hub, Writers in Tech is a podcast where content strategists, UX writers, and content designers share their well-kept industry secrets.

Content Rookie

You want to dive deeper into the practice and art of all things content? Then tune into Content Rookie, where Nicole Michaelis and her guests explore UX writing, content marketing, content design, and copywriting.

Design Systems

Design System Office Hours

In Design System Office Hours, design system practitioners Davy Fung and PJ Onori talk about design-led product ownership, scaling and adoption, community and engagement, design system team models, and much more.

Design Systems Podcast

The Design Systems Podcast interviews industry leaders and product makers to share best practices and explore the areas where design and development come together.

  • 🎙 Hosted by Chris Strahl
  • 🗓 New episodes ca. once to twice a month

Information Systems

The Informed Life

Information is key to deciding and acting. The Informed Life podcast explores how people organize information to get things done and how to better design, build, and use information systems.

Product Design

How I Built This

For How I Built This, Guy Raz interviews the world’s best-known entrepreneurs to learn how they built their iconic brands. They reveal their moments of doubt and failure and share insights on their eventual success.

  • 🎙 Hosted by Guy Raz
  • 🗓 New episodes on Mondays and Thursdays

The Product Design Podcast

The Product Design Podcast invites the best and brightest in product design to dig into how they got where they are today, what mistakes they made along the way, and what advice they have for you as you navigate the world of product design.

  • 🎙 Hosted by Seth Coelen
  • 🗓 Ca. two to three new episodes per month

Better Product

Better Product shares the stories of industry-leading companies whose products have a soul, mission, and vision. Through conversations with CEOs, entrepreneurs, and innovators, hosts Christian Beck and Meghan Pfeifer explore what it takes to build better products.

New Layer

New Layer is a podcast on everything related to product design, discussing design careers, tools, education, critique, and much more. The podcast has retired, but with two years of weekly episodes, the archive is still a treasure chest.


Design Better Podcast

Currently in its seventh season, the Design Better Podcast by InVision explores what it takes to make work more collaborative, creative, inclusive, and impactful throughout your organization.


The Futur Podcast

The Futur Podcast explores the overlap between design, marketing, and business. In each episode, Chris Do invites a new guest from the worlds of design, technology, marketing, business, philosophy, and personal development to understand what drives them and what we all can learn from it.

  • 🎙 Hosted by Chris Do
  • 🗓 New episodes weekly

Career And Leadership

Honest UX Talks

Anfisa Bogomolova and Ioana Teleanu together have 20 years of experience in the UX field. In Honest UX Talks, they share their lessons learned about UX design careers, challenges, portfolios, mental health, and, of course, all things UX.

The UX Hustle Podcast

The UX Hustle Podcast is a show with a focus on crafting and navigating a UX career and refining your UX process to become better at what you do. It also explores how to apply UX to your life to get more done, with low stress.

Finding Our Way

In Finding Our Way, hosts Peter Merholz and Jesse James Garrett navigate the challenges and opportunities of design and design leadership.

Google Design Podcasts

Google Design Podcasts is a collection of podcasts that gives you design inspiration and insights. Method explores the career journeys of designers at Google, while Design Notes goes in-depth with designers working in diverse creative disciplines.


Revision Path

Revision Path showcases Black designers, artists, developers, and digital creatives from all over the world. Through weekly in-depth interviews, you’ll learn about their work, their goals, and what inspires them as creative individuals.

Technically Speaking

Technically Speaking is a podcast by Harrison Wheeler about BIPOC designers, entrepreneurs, and technologists sharing their unique stories of triumph and resilience at the intersection of product design.

The Future Of UX

Rosenfeld Review Podcast

What shifts does UX face? And how can individuals and teams respond in ways that drive success? That’s what Lou Rosenfeld wants to find out by inviting changemakers in the UX world and beyond to the Rosenfeld Review Podcast.

  • 🎙 Hosted by Lou Rosenfeld
  • 🗓 Ca. one to two new episodes per month

The Sustainable UX Podcast

The Sustainable UX Podcast is for everyone who wants to make an impact for a sustainable future. In each episode, the hosts Bavo Lodewyckx and Thorsten Jonas invite you to meet people from around the world who try to save the world through and within UX, design, and tech.

Future Of UX

In every episode of the Future of UX podcast, Patricia Reiners talks to leading UX/UI designers and digital pioneers about the future and how we are going to design a great user experience with new technologies.

Creative Culture

Design Matters

Design Matters started out in 2005 as a little radio show and soon became the first podcast about design and an inquiry into the broader world of creative culture. Among the guests are designers, writers artists, curators, musicians, and other luminaries of contemporary thought.


99% Invisible

99% Invisible has grown from a four-minute spot on broadcast radio to an enormously popular narrative podcast with listeners all over the world. It dives deep into the things we don’t think about — the unnoticed architecture and design that shape our world.


Darknet Diaries

How about a peek inside the dark side of the web? Darknet Diaries is a podcast about hackers, breaches, shadow government activity, hacktivism, cybercrime, and all the things that dwell on the hidden parts of the network.

Last But Not Least…

Did you know that there’s a Smashing Podcast, too? In each episode, host Drew McLellan talks to design and development experts about their work on the web, as well as catching you up with the latest news and articles at Smashing Magazine. And, well, it’s suitable for cats, too. 😉

If you have a favorite UX podcast that is not mentioned in this post — or maybe you’re running one yourself — please let us know in the comments below. We’d love to hear about it!

Readability for SEO: Myths and Reality

A metric for the readability of an article is imprecise and often inaccurate. And there’s no evidence that readability is a direct Google ranking factor.

The post Readability for SEO: Myths and Reality appeared first on Practical Ecommerce.

Ecommerce Product Releases: February 1, 2023

This installment of our long-running series includes new services for digital wallets, in-video search, shipping, SEO, headless development, omnichannel fulfillment, and more.

The post Ecommerce Product Releases: February 1, 2023 appeared first on Practical Ecommerce.

Understanding App Directory Architecture In Next.js

Since Next.js 13 release, there’s been some debate about how stable the shiny new features packed in the announcement are. On “What’s New in Next.js 13?” we have covered the release announced and established that though carrying some interesting experiments, Next.js 13 is definitely stable. And since then, most of us have seen a very clear landscape when it comes to the new <Link> and <Image> components, and even the (still beta) @next/font; these are all good to go, instant profit. Turbopack, as clearly stated in the announcement, is still alpha: aimed strictly for development builds and still heavily under development. Whether you can or can’t use it in your daily routine depends on your stack, as there are integrations and optimizations still somewhere on the way. This article’s scope is strictly about the main character of the announcement: the new App Directory architecture (AppDir, for short).

Because the App directory is the one that keeps bringing questions due to it being partnered with an important evolution in the React ecosystem — React Server Components — and with edge runtimes. It clearly is the shape of the future of our Next.js apps. It is experimental though, and its roadmap is not something we can consider will be done in the next few weeks. So, should you use it in production now? What advantages can you get out of it, and what are the pitfalls you may find yourself climbing out of? As always, the answer in software development is the same: it depends.

What Is The App Directory Anyway?

It is the new strategy for handling routes and rendering views in Next.js. It is made possible by a couple of different features tied together, and it is built to make the most out of React concurrent features (yes, we are talking about React Suspense). It brings, though, a big paradigm shift in how you think about components and pages in a Next.js app. This new way of building your app has a lot of very welcomed improvements to your architecture. Here’s a short, non-exhaustive list:

  • Partial Routing.
    • Route Groups.
    • Parallel Routes.
    • Intercepting Routes.
  • Server Components vs. Client Components.
  • Suspense Boundaries.
  • And much more, check the features overview in the new documentation.

A Quick Comparison

When it comes to the current routing and rendering architecture (in the Pages directory), developers were required to think of data fetching per route.

  • getServerSideProps: Server-Side Rendered;
  • getStaticProps: Server-Side Pre-Rendered and/or Incremental Static Regeneration;
  • getStaticPaths + getStaticProps: Server-Side Pre-Rendered or Static Site Generated.

Historically, it hadn’t yet been possible to choose the rendering strategy on a per-page basis. Most apps were either going full Server-Side Rendering or full Static Site Generation. Next.js created enough abstractions that made it a standard to think of routes individually within its architecture.

Once the app reaches the browser, hydration kicks in, and it’s possible to have routes collectively sharing data by wrapping our _app component in a React Context Provider. This gave us tools to hoist data to the top of our rendering tree and cascade it down toward the leaves of our app.

import { type AppProps } from 'next/app'; export default function MyApp({ Component, pageProps }: AppProps) { return ( <SomeProvider> <Component {...pageProps} /> </SomeProvider>

The ability to render and organize required data per route made this approach an almost good tool for when data absolutely needed to be available globally in the app. And while this strategy will allow data to spread throughout the app, wrapping everything in a Context Provider bundles hydration to the root of your app. It is not possible anymore to render any branches on that tree (any route within that Provider context) on the server.

Here, enters the Layout Pattern. By creating wrappers around pages, we could opt in or out of rendering strategies per route again instead of doing it once with an app-wide decision. Read more on how to manage states in the Pages Directory on the article “State Management in Next.js” and on the Next.js documentation.

The Layout Pattern proved to be a great solution. Being able to granularly define rendering strategies is a very welcomed feature. So the App directory comes in to put the layout pattern front and center. As a first-class citizen of Next.js architecture, it enables enormous improvements in terms of performance, security, and data handling.

With React concurrent features, it’s now possible to stream components to the browser and let each one handle its own data. So rendering strategy is even more granular now — instead of page-wide, it’s component-based. Layouts are nested by default, which makes it more clear to the developer what impacts each page based on the file-system architecture. And on top of all that, it is mandatory to explicitly turn a component client-side (via the “use client” directive) in order to use a Context.

Building Blocks Of The App Directory

This architecture is built around the Layout Per Page Architecture. Now, there is no _app, neither is there a _document component. They have both been replaced by the root layout.jsx component. As you would expect, that’s a special layout that will wrap up your entire application.

export function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <body> {children} </body> </html>

The root layout is our way to manipulate the HTML returned by the server to the entire app at once. It is a server component, and it does not render again upon navigation. This means any data or state in a layout will persist throughout the lifecycle of the app.

While the root layout is a special component for our entire app, we can also have root components for other building blocks:

  • loading.jsx: to define the Suspense Boundary of an entire route;
  • error.jsx: to define the Error Boundary of our entire route;
  • template.jsx: similar to the layout, but re-renders on every navigation. Especially useful to handle state between routes, such as in or out transitions.

All of those components and conventions are nested by default. This means that /about will be nested within the wrappers of / automatically.

Finally, we are also required to have a page.jsx for every route as it will define the main component to render for that URL segment (as known as the place you put your components!). These are obviously not nested by default and will only show in our DOM when there’s an exact match to the URL segment they correspond to.

There is much more to the architecture (and even more coming!), but this should be enough to get your mental model right before considering migrating from the Pages directory to the App directory in production. Make sure to check on the official upgrade guide as well.

Server Components In A Nutshell

React Server Components allow the app to leverage infrastructure towards better performance and overall user experience. For example, the immediate improvement is on bundle size since RSC won’t carry over their dependencies to the final bundle. Because they’re rendered in the server, any kind of parsing, formatting, or component library will remain on the server code. Secondly, thanks to their asynchronous nature, Server Components are streamed to the client. This allows the rendered HTML to be progressively enhanced on the browser.

So, Server Components lead to a more predictable, cacheable, and constant size of your final bundle breaking the linear correlation between app size and bundle size. This immediately puts RSC as a best practice versus traditional React components (which are now referred to as client components to ease disambiguation).

On Server Components, fetching data is also quite flexible and, in my opinion, feels closer to vanilla JavaScript — which always smooths the learning curve. For example, understanding the JavaScript runtime makes it possible to define data-fetching as either parallel or sequential and thus have more fine-grained control on the resource loading waterfall.

  • Parallel Data Fetching, waiting for all:
import TodoList from './todo-list' async function getUser(userId) { const res = await fetch(`https://<some-api>/user/${userId}`); return res.json()
} async function getTodos(userId) { const res = await fetch(`https://<some-api>/todos/${userId}/list`); return res.json()
} export default async function Page({ params: { userId } }) { // Initiate both requests in parallel. const userResponse = getUser(userId) const = getTodos(username) // Wait for the promises to resolve. const [user, todos] = await Promise.all([userResponse, todosResponse]) return ( <> <h1>{user.name}</h1> <TodoList list={todos}></TodoList> </> )
  • Parallel, waiting for one request, streaming the other:
async function getUser(userId) { const res = await fetch(`https://<some-api>/user/${userId}`); return res.json()
} async function getTodos(userId) { const res = await fetch(`https://<some-api>/todos/${userId}/list`); return res.json()
} export default async function Page({ params: { userId } }) { // Initiate both requests in parallel. const userResponse = getUser(userId) const todosResponse = getTodos(userId) // Wait only for the user. const user = await userResponse return ( <> <h1>{user.name}</h1> <Suspense fallback={<div>Fetching todos...</div>}> <TodoList listPromise={todosResponse}></TodoList> </Suspense> </> )
} async function TodoList ({ listPromise }) { // Wait for the album's promise to resolve. const todos = await listPromise; return ( <ul> {todos.map(({ id, name }) => ( <li key={id}>{name}</li> ))} </ul> );

In this case, <TodoList> receives an in-flight Promise and needs to await it before rendering. The app will render the suspense fallback component until it’s all done.

  • Sequential Data Fetching fires one request at a time and awaits for each:
async function getUser(username) { const res = await fetch(`https://<some-api>/user/${userId}`); return res.json()
} async function getTodos(username) { const res = await fetch(`https://<some-api>/todos/${userId}/list`); return res.json()
} export default async function Page({ params: { userId } }) { const user = await getUser(userId) return ( <> <h1>{user.name}</h1> <Suspense fallback={<div>Fetching todos...</div>}> <TodoList userId={userId} /> </Suspense> </> )
} async function TodoList ({ userId }) { const todos = await getTodos(userId); return ( <ul> {todos.map(({ id, name }) => ( <li key={id}>{name}</li> ))} </ul> );

Now, Page will fetch and wait on getUser, then it will start rendering. Once it reaches <TodoList>, it will fetch and wait on getTodos. This is still more granular than what we are used to it with the Pages directory.

Important things to note:

  • Requests fired within the same component scope will be fired in parallel (more about this at Extended Fetch API below).
  • Same requests fired within the same server runtime will be deduplicated (only one is actually happening, the one with the shortest cache expiration).
  • For requests that won’t use fetch (such as third-party libraries like SDKs, ORMs, or database clients), route caching will not be affected unless manually configured via segment cache configuration.
export const revalidate = 600; // revalidate every 10 minutes export default function Contributors({ params
}: { params: { projectId: string };
}) { const { projectId } = params const { contributors } = await myORM.db.workspace.project({ id: projectId }) return <ul>{*/ ... */}</ul>;

To point out how much more control this gives developers: when within the pages directory, rendering would be blocked until all data is available. When using getServerSideProps, the user would still see the loading spinner until data for the entire route is available. To mimic this behavior in the App directory, the fetch requests would need to happen in the layout.tsx for that route, so always avoid doing it. An “all or nothing” approach is rarely what you need, and it leads to worse perceived performance as opposed to this granular strategy.

Extended Fetch API

The syntax remains the same: fetch(route, options). But according to the Web Fetch Spec, the options.cache will determine how this API will interact with the browser cache. But in Next.js, it will interact with the framework server-side HTTP Cache.

When it comes to the extended Fetch API for Next.js and its cache policy, two values are important to understand:

  • force-cache: the default, looks for a fresh match and returns it.
  • no-store or no-cache: fetches from the remote server on every request.
  • next.revalidate: the same syntax as ISR, sets a hard threshold to consider the resource fresh.
fetch(`https://route`, { cache: 'force-cache', next: { revalidate: 60 } })

The caching strategy allows us to categorize our requests:

  • Static Data: persist longer. E.g., blog post.
  • Dynamic Data: changes often and/or is a result of user interaction. E.g., comments section, shopping cart.

By default, every data is considered static data. This is due to the fact force-cache is the default caching strategy. To opt out of it for fully dynamic data, it’s possible to define no-store or no-cache.

If a dynamic function is used (e.g., setting cookies or headers), the default will switch from force-cache to no-store!

Finally, to implement something more similar to Incremental Static Regeneration, you’ll need to use next.revalidate. With the benefit that instead of being defined for the entire route, it only defines the component it’s a part of.

Migrating From Pages To App

Porting logic from Pages directory to Apps directory may look like a lot of work, but Next.js has worked prepared to allow both architectures to coexist, and thus migration can be done incrementally. Additionally, there is a very good migration guide in the documentation; I recommend you to read it fully before jumping into a refactoring.

Guiding you through the migration path is beyond the scope of this article and would make it redundant to the docs. Alternatively, in order to add value on top of what the official documentation offers, I will try to provide insight into the friction points my experience suggests you will find.

The Case Of React Context

In order to provide all the benefits mentioned above in this article, RSC can’t be interactive, which means they don’t have hooks. Because of that, we have decided to push our client-side logic to the leaves of our rendering tree as late as possible; once you add interactiveness, children of that component will be client-side.

In a few cases pushing some components will not be possible (especially if some key functionality depends on React Context, for example). Because most libraries are prepared to defend their users against Prop Drilling, many create context providers to skip components from root to distant descendants. So ditching React Context entirely may cause some external libraries not to work well.

As a temporary solution, there is an escape hatch to it. A client-side wrapper for our providers:

// /providers.jsx
‘use client’ import { type ReactNode, createContext } from 'react'; const SomeContext = createContext(); export default function ThemeProvider({ children }: { children: ReactNode }) { return ( <SomeContext.Provider value="data"> {children} </SomeContext.Provider> );

And so the layout component will not complain about skipping a client component from rendering.

// app/.../layout.jsx
import { type ReactNode } from 'react';
import Providers from ‘./providers’; export default function Layout({ children }: { children: ReactNode }) { return ( <Providers>{children}</Providers> );

It is important to realize that once you do this, the entire branch will become client-side rendered. This approach will take everything within the <Providers> component to not be rendered on the server, so use it only as a last resort.

TypeScript And Async React Elements

When using async/await outside of Layouts and Pages, TypeScript will yield an error based on the response type it expects to match its JSX definitions. It is supported and will still work in runtime, but according to Next.js documentation, this needs to be fixed upstream in TypeScript.

For now, the solution is to add a comment in the above line {/* @ts-expect-error Server Component */}.

Client-side Fetch On The Works

Historically, Next.js has not had a built-in data mutation story. Requests being fired from the client side were at the developer’s own discretion to figure out. With React Server Components, this is bound for a chance; the React team is working on a use hook which will accept a Promise, then it will handle the promise and return the value directly.

In the future, this will supplant most bad cases of useEffect in the wild (more on that in the excellent talk “Goodbye UseEffect”) and possibly be the standard for handling asynchronicity (fetching included) in client-side React.

For the time being, it is still recommended to rely on libraries like React-Query and SWR for your client-side fetching needs. Be especially aware of the fetch behavior, though!

So, Is It Ready?

Experimenting is at the essence of moving forward, and we can’t make a nice omelet without breaking eggs. I hope this article has helped you answer this question for your own specific use case.

If on a greenfield project, I’d possibly take App directory for a spin and keep Page directory as a fallback or for the functionality that is critical for business. If refactoring, it would depend on how much client-side fetching I have. Few: do it; many: probably wait for the full story.

Let me know your thoughts on Twitter or in the comments below.

Further Reading On SmashingMag

The Magic Of February (2023 Wallpapers Edition)

As designers we usually turn to different sources of inspiration, and, well, sometimes the best inspiration lies right in front of us. With that in mind, we embarked on our wallpapers adventure more than eleven years ago. The idea: to provide you with unique and inspiring desktop wallpapers each month anew. Wallpapers created by the community for the community.

We are very thankful to all artists and designers who have contributed and are still diligently contributing to this challenge, who tickle their creativity to keep the steady stream of wallpapers flowing. This post features their artworks for February 2023. All wallpapers come in two versions — with and without a calendar — and can be downloaded for free. At the end of this post, we also compiled some February “oldies but goodies” from our archives for you. Maybe you’ll discover one of your almost-forgotten favorites in there, too? Enjoy!

  • You can click on every image to see a larger preview,
  • We respect and carefully consider the ideas and motivation behind each and every artist’s work. This is why we give all artists the full freedom to explore their creativity and express emotions and experience through their works. This is also why the themes of the wallpapers weren’t anyhow influenced by us but rather designed from scratch by the artists themselves.
  • Submit a wallpaper!
    Did you know that you could get featured in our next wallpapers post, too? We are always looking for creative talent.


“I wanted to draw some very cozy place, both realistic and cartoonish, filled with little details. A space with a slightly unreal atmosphere that some great shops or cafes have. A mix of plants, books, bottles, and shelves seemed like a perfect fit. I must admit it took longer to draw than most of my other pictures! But it was totally worth it. Watch the making-of.” — Designed by Vlad Gerasimov from Georgia.

Mesmerising Spring

“Mesmerising Spring Rain by Clean Sky Rain Library.” — Designed by Bhabna Basak from India.

This Is Really A Wild Place Up Here

“In times of never-greater hype around the future of technological advancements, we go back to another tech revolution of the past. February 9th marks the day of Apollo 14’s landing on the moon, the third in NASA’s crewed space program. Our February calendar design aims to connect the tech endeavors of the present and past and serve as a reminder that innovation should always be used for a good cause.” — Designed by PopArt Studio from Serbia.

Panettone 278 U

Designed by Ricardo Gimenes from Sweden.

Love Is In The Air

“February comes with Valentine’s vibes. Valentine’s week begins on February 7 which is celebrated as Rose Day and lasts until the most important day, Valentine’s Day, on February 14. This week, from the 7th to the 14th is likewise called the Love Week, Valentine’s Week, or the Romance Week. So I decided to design this wallpaper to remind everyone to enjoy the loving vibes throughout this week.” — Designed by Hrishikesh Shome from India.

Winter In Dubai

“Winter in Dubai is less winter. There we can enjoy pleasant temperatures while we watch the sunset. Did you sign up?” — Designed by Veronica Valenzuela from Spain.

Moments That Are Everything

“February is the month of love. There are moments that don’t seem like anything but are everything.” — Designed by Kasturi Palmal from India.

Happy Maha Shivratri

“Discover your hidden potential and inner self as you meditate on the thought of reaching closer to Lord Shiva on the occasion of Maha Shivratri.” — Designed by ThemeSelection from India.

Paper Hearts

“Happy Valentine’s Day!” — Designed by Viktor Hanacek from Czech Republic.

Farewell C/2022 E3 ZTF

“On February 1, the recently discovered comet C/2022 E3 ZTF is at its nearest position to Earth. Whaouh, it’s not every year we can see a comet in the sky and this one will return in… well, we’ll never see it again. Farewell little comet!” — Designed by Philippe Brouard from France.


Designed by Ricardo Gimenes from Sweden.

Flowers And Snowflakes

“Our designers decided not to overuse the topic of Valentine’s Day and used its basic attributes and a pure pastel blue color scheme for the wallpaper instead. But if you still need more red and pink colors, check out our listicle with more options.” — Designed by MasterBundles from Ukraine.

Love Balloons

“Valentine’s Day is coming!” — Designed by Viktor Hanacek from Czech Republic.

Oldies But Goodies

Whether it’s a brave icebreaker that confronts even the most adverse weather conditions, a piece of design wisdom, or, well, french fries — many things have inspired folks from across the globe to create a February wallpaper for our monthly series. Below you’ll find a little best-of from our wallpapers archives. Please note that these wallpapers don’t come with a calendar.

Magic Of Music

“Please visit Vladstudio website if you like my works!” — Designed by Vlad Gerasimov from Russia.

Love Is In The Play!

“Forget Lady and the Tramp and their spaghetti kiss, ’cause Snowflake and Cloudy are enjoying their bliss. The cold and chilly February weather made our kitties knit themselves a sweater. Knitting and playing, the kitties tangled in the yarn and fell in love in your neighbor’s barn.” — Designed by PopArt Studio from Serbia.

True Love

Designed by Ricardo Gimenes from Sweden.

Principles Of Good Design

“The simplicity seen in the work of Dieter Rams which has ensured his designs from the 50s and 60s still hold a strong appeal.” — Designed by Vinu Chaitanya from India.

Love Is Worth Fighting For

Designed by Maria Keller from Mexico.

February Ferns

Designed by Nathalie Ouederni from France.

Time Thief

“Who has stolen our time? Maybe the time thief, so be sure to enjoy the other 28 days of February.” — Designed by Colorsfera from Spain.

Dark Temptation

“A dark romantic feel, walking through the city on a dark and rainy night.” — Designed by Matthew Talebi from the United States.

French Fries

Designed by Doreen Bethge from Germany.

Good Times Ahead

Designed by Ricardo Gimenes from Sweden.

The Great Beyond

Designed by Lars Pauwels from Belgium.

Farewell, Winter

“Although I love winter (mostly because of the fun winter sports), there are other great activities ahead. February, the last winter month, this year is even one day longer. But I don’t mind. Thanks, winter, and see you next year!” — Designed by Igor Izhik from Canada.


Designed by Elise Vanoorbeek from Belgium.

Love Angel Vader

“Valentine’s Day is coming? Noooooooooooo!” — Designed by Ricardo Gimenes from Sweden.

Ice Cream Love

“My inspiration for this wallpaper is the biggest love someone can have in life: the love for ice cream!” — Designed by Zlatina Petrova from Bulgaria.

The Boy Who Will Never Grow Up

Designed by Ricardo Gimenes from Sweden.

Dog Year Ahead

Designed by PopArt Studio from Serbia.

“Greben” Icebreaker

“Danube is Europe’s second largest river, connecting ten different countries. In these cold days, when ice paralyzes rivers and closes waterways, a small but brave icebreaker called Greben (Serbian word for ‘reef’) seems stronger than winter. It cuts through the ice on Đerdap gorge (Iron Gate) – the longest and biggest gorge in Europe – thus helping the production of electricity in the power plant. This is our way to give thanks to Greben!” — Designed by PopArt Studio from Serbia.


“I live in Madison, WI, which is famous for its breweries. Wisconsin even named their baseball team “The Brewers.” If you like beer, brats, and lots of cheese, it’s the place for you!” — Designed by Danny Gugger from the United States.


Designed by Xenia Latii from Germany.

Like The Cold Side Of A Pillow

Designed by Sarah Tanner from the United States.

Minimalistic Love

“This minimalistic love logo is designed from geometric shapes, where the heart represents the letter ‘O’ and love. The anchor represents the letter ‘V’ very delicately and stylish and it symbolizes your wanderlust. The anchor is a symbol of adventure and travels.” — Designed by Antun Hirsman from Croatia.

Winter Wonderland

“In February, nature shows its creativity. Our artwork occurs when it is being drawn.” — Designed by Ana Masnikosa from Belgrade, Serbia.

13 AI Chatbots for Business

ChatGPT demonstrates the stunning benefits of artificial intelligence. Many other providers offer impressive AI-driven tools for customer service, process automation, and more. Here are 13 of them.

The post 13 AI Chatbots for Business appeared first on Practical Ecommerce.

The 5 R’s of Merchandising (for Ecommerce)

A 100-year-old merchandising concept applies to modern-day ecommerce retailers — the right people, right product, right quantity, right price, right time.

The post The 5 R’s of Merchandising (for Ecommerce) appeared first on Practical Ecommerce.

Easy SVG Customization And Animation: A Practical Guide

Scalable Vector Graphics (SVG) have been a staple in Web Development for quite some time, and for a good reason. They can be scaled up or down without loss of quality due to their vector properties. They can be compressed and optimized due to the XML format. They can also be easily edited, styled, animated, and changed programmatically.

At the end of the day, SVG is a markup language. And just as we can use CSS and JavaScript to enhance our HTML, we can use them the same on SVGs. We could add character and flourishes to our graphic elements, add interactions, and shape truly delightful and memorable user experiences. This optional but crucial detail is often overlooked when building projects, so SVGs end up somewhat underutilized beyond their basic graphical use cases.

How can we even utilize SVGs beyond just using them statically in our projects?

Take the “The State of CSS 2021” landing page, for example. This SVG Logo has been beautifully designed and animated by Christopher Kirk-Nielsen. Although this logo would have looked alright just as a static image, it wouldn’t have had as much of an impact and drawn attention without this intricate animation.

Let’s go even further — SVG, HTML, CSS, and JavaScript can be combined and used to create delightful, interactive, and stunning projects. Check out Sarah Drasner’s incredible work. She has also written a book and has a video course on the topic.

Let’s add it to our HTML and create a simple button component.

<button type="button"> <svg width="24" height="24" viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="..." fill="#C2CCDE" /></svg> Add to favorites

Our button already has some background and text color styles applied to it so let’s see what happens when we add our SVG star icon to it.

Our SVG icon has a fill property applied to it, more specifically, a fill="#C2CCDE" in SVG’s path element. This icon could have come from the SVG library or even exported from a design file, so it makes sense for a color to be exported alongside other graphical properties.

SVG elements can be targeted by CSS like any HTML element, so developers usually reach for the CSS and override the fill color.

.button svg * { fill: var(--color-text);

However, this is not an ideal solution as this is a greedy selector, and overriding the fill attribute on all elements can have unintended consequences, depending on the SVG markup. Also, fill is not the only property that affects the element’s color.

Let’s showcase this downside by creating a new button and adding a Google logo icon. SVG markup is a bit more complex than our star icon, as it has multiple path elements. SVG elements don’t have to be all visible, there are cases when we want to use them in different ways (as a clipping region, for example), but we won’t go into that. Just keep in mind that greedy selectors that target SVG elements and override their fill properties can produce unexpected results.

 <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"> <path d="..." fill="#4285F4" /> <path d="..." fill="#34A853" /> <path d="..." fill="#FBBC05" /> <path d="..." fill="#EA4335" /> <path d="..." fill="none" /> </svg>

We can look at the issue from a different perspective. Instead of looking for a silver bullet CSS solution, we can simply edit our SVG. We already know that the fill property affects the SVG element’s color so let’s see what we can do to make our icons more customizable.

Let’s use a very underutilized CSS value: currentColor. I’ve talked about this awesome value in one of my previous articles.

Often referred to as “the first CSS variable,” currentColor is a value equal to the element’s color property. It can be used to assign a value equal to the value of the color property to any CSS property which accepts a color value. It forces a CSS property to inherit the value of the color property.

If you are looking for more, CSS-Tricks keeps a comprehensive list of various SVG optimization tools with plenty of information and articles on the topic.

Using SVGs With Popular JavaScript-Based Frameworks

Many popular JavaScript frameworks like React have fully integrated SVG in their toolchains to make the developer experience easier. In React, this could be as simple as importing the SVG as a component, and the toolkit would do all the heavy lifting optimizing it.

import React from 'react';
import {ReactComponent as ReactLogo} from './logo.svg'; const App = () => { return ( <div className="App"> <ReactLogo /> </div> );
export default App;

However, as Jason Miller and many other developers have noted, including the SVG markup in JSX bloats the JavaScript bundle and makes the SVG less performant as a result. Instead of just having the browser parse and render an SVG, with JSX, we have expensive extra steps added to the browser. Remember, JavaScript is the most expensive Web resource, and by injecting SVG markup into JSX, we’ve made SVG as expensive as well.

One solution would be to create SVG symbol objects and include them with SVG use. That way, we’ll be defining the SVG icon library in HTML, and we can instantiate it and customize it in React as much as we need to.

<!-- Definition -->
<svg viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg"> <symbol id="myIcon" width="24" height="24" viewBox="0 0 24 24"> <!-- ... --> </symbol> <!-- ... -->
</svg> <!-- Usage -->
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <use href="#myIcon" />

Breathing Life Into SVGs

Animating SVGs can be easy and fun. It takes just a few minutes to create some simple and effective animations and interactions. If you are unsure which animation would be ideal for a graphic or should you animate it at all, it’s best to consult with the designer. You can even look for some similar examples and use cases on Dribble or other similar websites.

It’s also important to keep in mind that animations should be tasteful, add to the overall user experience, and serve some purpose (draw the user’s attention, for example).

We’ll cover various use cases that you might encounter on your projects. Let’s start with a really sweet example.

Animating A Cookie Banner

Some years ago, I was working on a project where a designer made an adorable cookie graphic for an unobtrusive cookie consent popup to make the element more prominent. This cookie graphic was whimsical and a bit different from the general design of the website.

I’ve created the element and added the graphic, but when looking at the page as a whole, it felt kind of lifeless, and it didn’t stand out as much as we thought it will. The user needed to accept cookies as the majority of website functionality depended on cookies. We wanted to create an unobtrusive banner that doesn’t block user navigation from the outset, so I decided to animate it to make it more prominent and add a bit of flourish and character.

I’ve decided to create three animations that’ll be applied to the cookie SVG:

  • Quick and snappy rolling fade-in entry animation;
  • Repeated wiggle animation with a good amount of delay in between;
  • Repeating and subtle eye sparkle animation.

Here’s the final result of the element that we’ll be creating. We’ll cover each animation step by step.

Let’s store it in a CSS variable so that we can reuse it for the repeatable wiggle movement animation.

--transition-bounce: cubic-bezier(0.2, 0.7, 0.4, 1.65);

Let’s put everything together, set a duration value and fill-mode, and add the animation to our svg element.

/* Our SVG element */
.cookie-notice__graphic { opacity: 0; /* Should not be visible at the start */ animation: enter 0.8s var(--transition-bounce) forwards;

Let’s check out what we’ve created. It already looks really nice. Notice how the bouncing easing function made a lot of difference to the overall look and feel of the whole element.

@keyframes wiggle { /* Stands still */ 0% { transform: translate3d(0, 0, 0) rotateZ(17deg); } /* Starts moving */ 45% { transform: translate3d(0, 0, 0) rotateZ(17deg); } /* Pulls back */ 50% { transform: translate3d(-10%, 0, 0) rotateZ(8deg); } /* Moves forward */ 55% { transform: translate3d(6%, 0, 0) rotateZ(24deg); } /* Returns to starting position */ 60% { transform: translate3d(0, 0, 0) rotateZ(17deg); } /* Stands still */ 100% { transform: translate3d(0, 0, 0) rotateZ(17deg); }
/* Our SVG element */
.cookie-notice__graphic { opacity: 0; animation: enter 0.8s var(--transition-bounce) forwards, wiggle 6s 3s var(--transition-bounce) infinite;

SVG elements can have a CSS class attribute, so we’ll use that to target them. Let’s add the class attribute to the two path elements that we identified.

<!-- ... -->
<path fill="#351f17" d="..." />
<path class="cookie__eye" fill="#fff" d="..." />
<path fill="#351f17" d="..." />
<path class="cookie__eye" fill="#fff" d="..." />
<!-- ... -->

We want to make cookie’s eyes sparkle. I got this idea from a music video for a song by Devin Townsend. You can see the animation play at the 5-minute mark. It just goes to show how you can find ideas pretty much anywhere.

Let’s just change the scale and opacity. Notice how so far, we’ve relied only on those two attributes for all three animations, which are quite different from each other.

@keyframes sparkle { from { opacity: 0.95; transform: scale(0.95); } to { opacity: 1; transform: scale(1); }

We want this animation to repeat without delay. It should be subtle enough to blend in nicely with the graphic and the overall element and not obtrusive for the user. As for the easing function, we’ll do something different. We’ll use staircase functions to achieve that quick and snappy transition between the two animation states (our from and to values).

We need to be careful here. Transform origin is going to be set relative to the parent SVG element’s viewbox and not the element itself. So if we set transform-origin: center center, the transformation will use the center coordinates of the parent SVG and not the path element. We can easily fix that by setting a transform-box property to fill-box.

The nearest SVG viewport is used as the reference box. If a viewBox attribute is specified for the SVG viewport creating element, the reference box is positioned at the origin of the coordinate system established by the viewBox attribute, and the dimension of the reference box is set to the width and height values of the viewBox attribute.

.cookie__eye { animation: sparkle 0.15s 1s steps(2, jump-none) infinite alternate; transform-box: fill-box; transform-origin: center center;

Last but not least, let’s respect the user’s accessibility preferences and turn off all animations if they have it set.

@media (prefers-reduced-motion: reduce) { *, ::before, ::after { animation-delay: -1ms !important; animation-duration: 1ms !important; animation-iteration-count: 1 !important; background-attachment: initial !important; scroll-behavior: auto !important; transition-duration: 0s !important; transition-delay: 0s !important; }

Here is the final result. Feel free to play around with the demo and experiment with keyframe values and easing values to change the look and feel of the animation.

Let’s take a closer look at the SVG we’ll be working with. It consists of a few dozen circle elements.

<!-- ... -->
<circle cx="103.5" cy="34.5" r="11.3"></circle>
<circle cx="172.5" cy="34.5" r="15.7"></circle>
<circle cx="310.5" cy="34.5" r="24.6"></circle>
<circle cx="517.5" cy="34.5" r="34.5"></circle>
<circle cx="586.5" cy="34.5" r="34.5"></circle>
<circle cx="655.5" cy="34.5" r="33.4"></circle>
<!-- ... -->

Let’s start by adding a bit of opacity to our background and making it more chaotic. When we apply CSS transforms to elements inside SVG, they are transformed relative to the SVG’s main viewbox. That is why we’re getting a slightly chaotic displacement when applying a scale transform. We’ll use that to our advantage and not change the reference box.

To make things a little bit easier for us, we’ll use SASS. If you are unfamiliar with SASS and SCSS, you can view compiled CSS in CodePen below.

svg circle { opacity: 0.85; &:nth-child(2n) { transform: scale3d(0.75, 0.75, 0.75); opacity: 0.3;

With that in mind, let’s add some keyframes. We’ll use two sets of keyframes that we’ll apply randomly to our circle elements. Once again, we’ll leverage the scale transform displacement and change the opacity value.

@keyframes a { 0% { opacity: 0.8; transform: scale3d(1, 1, 1); } 100% { opacity: 0.3; transform: scale3d(0.75, 0.75, 0.75); }
} @keyframes b { 0% { transform: scale3d(0.75, 0.75 0.75); opacity: 0.3; } 100% { opacity: 0.8; transform: scale3d(1, 1, 1); }

Now, let’s use quite a few :nth-child selectors. Every odd child will use the a keyframes, while every even circle will use a b keyframes. We’ll use :nth-child selectors to play around with animation duration and animation delay values.

svg circle { opacity: 0.85; animation: a 10s cubic-bezier(0.45,0.05,0.55,0.95) alternate infinite; &:nth-child(2n) { transform: scale3d(0.75, 0.75, 0.75); opacity: 0.3; animation-name: b; animation-duration: 6s; animation-delay: 0.5s; } &:nth-child(3n) { animation-duration: 4s; animation-delay: 0.25s; } /* ... */

And, once again, just by playing around with opacity values and CSS transforms on our SVG and playing around with child selectors and animation parameters, we’ve managed to create a more interesting background for our hero container.

Here is a markup for our circle SVG.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="50" cy="50" r="50" fill-opacity=".03"/></svg>

Be careful not to inline too much data with base64, so stylesheets can be downloaded and parsed quickly. When we convert it to base64, we get this handy CSS background-image snippet:

background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48Y2lyY2xlIGN4PSI1MCIgY3k9IjUwIiByPSI1MCIgZmlsbC1vcGFjaXR5PSIuMDMiLz48L3N2Zz4=);

We can simply apply a simple animation where we offset the background-position by the background-size value and get this neat background animation.

.wrapper { animation: move-background 3.5s linear; background-image: url(data:image/svg+xml;base64,...); background-size: 96px; background-color: #16a757; /* ... */
} @keyframes move-background { from { background-position: 0 0; } to { background-position: 96px 0; }

Our example looks more interesting with this subtle moving animation going on in the background. Remember to respect users’ accessibility preferences and turn off the animations if they have a preference set.

Before diving into the animation, we need to cover two SVG properties that we’ll be using: stroke-dasharray and stroke-dashoffset. They’re integral for pulling off this animation.

Stroke can be converted to dashes with a certain length using a stroke-dasharray property.

And we can offset the positions of those strokes by a certain amount using the stroke-dashoffset property.

So, what’s this have to do with our drawing and erasing animation? Imagine what would happen if we could have a dash that covers the whole stroke length and offset it by the same value. In that case, the starting point of the stroke would be way past the ending point of the stroke, and we wouldn’t see it.

svg path { stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 800; /* Dash covering the whole stroke */ stroke-dashoffset: 800; /* Offset it to make it invisible */

If we animate the offset value from that value back to 0, the stroke would slowly become visible, as it was drawing itself.

svg path { /* ... */ animation: draw 6s linear infinite;
} @keyframes draw{ to { stroke-dashoffset: 0; /* Reduce offset to make it visible */ }

If we continue to animate the offset value from 0 to a negative value, we’d get the erasing effect.

svg path { /* ... */ animation: drawAndErase 6s linear infinite;
} @keyframes drawAndErase { to { stroke-dashoffset: -800; }

You’re probably wondering where the magical 800 pixel value came from. This value depends on the SVG and the length of the dash needed to cover the whole stroke length. It can be easily guessed, but Chris Coyier has a handy function that can do it for you. However, depending on the stroke properties and SVG shape, this function might not always return an ideal value, but it can guide you closer to it.

Check out the complete demo and feel free to play around with values to see how the stroke properties affect the animation. If you are looking for more examples, CodyHouse has covered a fun-looking button animation using the same trick.

Let’s start by adding the mouse-tracking eye animation. We’ll skip manually implementing this feature in JavaScript and use a handy library called watching-you.

Using the browser’s inspect element tool, we’ll find the target elements inside the SVG and add the eye-left and eye-right CSS classes to these elements, respectively.

<ellipse class="cls-5 eye eye-left" cx="245.15133" cy="134.57033" rx="5.31264" ry="8.61816" transform="translate(-33.47349 110.5587) rotate(-23.83807)" />
<ellipse class="cls-4 eye eye-right" cx="284.42686" cy="116.68559" rx="5.31264" ry="8.61816" transform="translate(-22.89477 124.9063) rotate(-23.83807)" />

We’ll configure the library and make it target the classes that we’ve added.

const optionsLeft = { power: 4, rotatable: false };
const watcherLeft = new WatchingYou(".eye-left", optionsLeft);
watcherLeft.start(); const optionsRight = { power: 3, rotatable: false };
const watcherRight = new WatchingYou(".eye-right", optionsRight);

We also need to remember to apply the transform-box property, so our eyes move around the center.

.eye { transform-box: fill-box; transform-origin: center center;

Let’s check out what we’ve got. With just a few lines of code and a tiny JavaScript library to do the heavy lifting, we’ve made the SVG element respond to the mouse position. Now that’s amazing, isn’t it?

Bowtie and hat animation will be created in a very similar way. Let’s start with a hat and find it using the browser’s inspect element tool. The hat graphic consists of two path elements, so let’s group them.

<g class="hat"> <path class="cls-6" d="..." /> <path class="cls-9" d="..." />

We’ll apply the same transform-box property and add a hat--active class that will run the animation when applied.

.hat { transform-box: fill-box; transform-origin: center bottom; cursor: pointer;
} .hat--active { animation: hatJump 1s cubic-bezier(0, 0.7, 0.5, 1.25);
} @keyframes hatJump { 0% { transform: rotateZ(0) translateY(0); } 50% { transform: rotateZ(-10deg) translateY(-50%); } 100% { transform: rotateZ(0) translateY(0); }

Finally, let’s set up a click event listener that applies an active class to the element and then removes it after the animation has finished running.

const hat = document.querySelector(".hat"); hat.addEventListener("click", function () { if (hat.classList.contains("hat--active")) { return; } // Add the active class. hat.classList.add("hat--active"); // Remove the active class after 1.2s. setTimeout(function () { hat.classList.remove("hat--active"); }, 1200);

We use the same trick with the bowtie element, only applying a different animation and class. Feel free to check out the CodePen demo for more details.

Let’s move on to the coffee machine. Notice we don’t have any SVG element acting as a coffee on our SVG, so we’ll need to add it ourselves. You should feel comfortable editing SVG markup and we don’t even have to break a sweat here. Let’s make it easy for ourselves and find and copy the coffee machine’s pipe rectangle, which is similar to the coffee stream shape we want to have. We just have to change the color to brown and slightly adjust the dimensions.

<!-- Pipe -->
<rect class="cls-12" x="137.81171" y="243.99883" width="6.21967" height="12.29272" transform="translate(281.84309 500.29037) rotate(-180)" /> <!-- Copied and adjusted Pipe rect to act as a coffee -->
<rect class="coffee" x="139" y="243.99883" width="4" height="12.29272" transform="translate(281.84309 500.29037) rotate(-180)" fill="brown" />

Like in the previous examples, let’s add active classes and their respective animation keyframes. We’ll compose the two animations and play around with duration and delay.

.lever, .coffee { transform-box: fill-box; transform-origin: center bottom;
} .lever { cursor: pointer; } .lever--active { animation: leverPush 2.5s linear;
} @keyframes leverPush { 0% { transform: translateY(0); } 8% { transform: translateY(50%); } 90% { transform: translateY(50%); } 100% { transform: translateY(0); }
} .coffee--active { animation: coffeeStream 2.4s 0.1s ease-out forwards;
} @keyframes coffeeStream { 0% { transform: translateY(0); } 5% { transform: translateY(50%); } 95% { transform: translateY(50%); } 100% { transform: translateY(150%); }

Let’s apply the active classes on click and remove them after the animation has finished running. And that’s it!

const lever = document.querySelector(".lever");
const coffee = document.querySelector(".coffee"); lever.addEventListener("click", function () { if (lever.classList.contains("lever--active")) { return; } lever.classList.add("lever--active"); coffee.classList.add("coffee--active"); setTimeout(function () { lever.classList.remove("lever--active"); coffee.classList.remove("coffee--active") }, 2500);

Check out the complete example below, and, as always, feel free to play around with the animations and experiment with other elements, like the speech bubble or making the coffee machine’s lights blink while coffee is pouring out. Have fun!

See the Pen Smashing cat interaction [forked] by Adrian Bece.


I hope that this article encourages you to play around and make some wonderful SVG animations and interactions and integrate this workflow into your day-to-day projects. We’ve used only a handful of tricks and CSS properties to create a whole variety of nice effects on the fly. With some extra time, knowledge, and effort, you can create some truly amazing and interactive graphics.

Feel free to reach out on Twitter and share your work. Happy to hear your thoughts and see what you come up with!


How ChatGPT Drives Ecommerce Conversions

ChatGPT can suggest bullet points, email subject lines, A/B tests, product recommendations, FAQs, and more. The suggestions aren’t perfect but definitely helpful.

The post How ChatGPT Drives Ecommerce Conversions appeared first on Practical Ecommerce.

Ridge Wallet CEO Aims for $1 Billion Exit

Sean Frank addresses the overall state of ecommerce in 2022, the perils of excessive debt, and his goal of selling the company within three years.

The post Ridge Wallet CEO Aims for $1 Billion Exit appeared first on Practical Ecommerce.