To build an online version of your physical mall with a multi-vendor structure, you need a platform that allows each vendor to manage their own storefront, catalog, and order fulfillment while centralizing the order processing. Based on your description, the platform should ideally support a B2B2C (Business-to-Business-to-Consumer) model and provide the following capabilities:
Centralized shopping cart for customers (aggregating products from multiple vendors)
Vendor-specific order fulfillment, customer service, and returns
Payment and commission handling
Seamless integration of vendor products with your platform
Scalable and customizable to fit your mall's specific needs
Let's explore some of the platforms you mentioned, including Mirakl, BigCommerce, and Shopify B2B, as well as other possible solutions.
1. Mirakl
Mirakl is a robust platform designed for marketplace management and can handle multi-vendor environments efficiently. It provides an end-to-end solution for building an online marketplace with a central shopping cart and individual vendor storefronts.
Pros:
Fully customizable and designed for multi-vendor models.
Allows each vendor to manage their own catalog, pricing, promotions, and fulfillment.
Handles vendor commissions, order routing, and payments.
Pricing is generally on the higher side, suited more for larger enterprises.
Can be complex to set up and maintain depending on your level of customization.
Recommendation: Mirakl is an excellent choice if you are looking for a comprehensive, enterprise-grade solution with extensive customization. It’s ideal for larger-scale operations and can handle complex workflows.
2. BigCommerce (B2B Edition)
BigCommerce is a well-known e-commerce platform that also supports multi-vendor marketplaces. Its B2B Edition specifically allows you to create a marketplace where vendors can manage their own products, catalogs, and orders.
Pros:
Supports B2B and B2C business models.
Allows for multi-vendor integration with custom storefronts.
Offers a robust API for integration with other systems.
Scalable, with a user-friendly interface for both admins and vendors.
Comprehensive payment processing options.
Cons:
The B2B edition might require customization for complex marketplace features.
Limited advanced marketplace functionality out of the box compared to specialized platforms like Mirakl.
Recommendation: BigCommerce is a good option for SMBs or those who want a simpler, easier-to-manage solution with multi-vendor capabilities. It is not as specialized in marketplace features as Mirakl but can be an excellent choice for growing your business with a solid foundation.
3. Shopify (B2B Solution)
Shopify offers a variety of tools that allow you to set up a multi-vendor marketplace. The Shopify B2B solution is specifically designed for businesses looking to integrate vendors, provide them with custom storefronts, and streamline the order process.
Pros:
User-friendly, even for those without technical expertise.
Vendor management apps (like Multi Vendor Marketplace or Shopify Plus features) enable product catalog and order management.
Strong app marketplace for additional functionality (e.g., for dropshipping, customer support).
Extensive support for payment, inventory, and shipping management.
Easy integration with dropshipping providers, payments, and fulfillment services.
Cons:
Can get costly, especially with apps and advanced features.
Marketplace functionalities are more limited out of the box, requiring third-party apps for full functionality.
Recommendation: Shopify is a great choice if you're looking for an easy-to-use platform with flexibility. It’s ideal for smaller vendors who want a plug-and-play solution with strong customization options via third-party apps.
4. Other Platforms to Consider:
WooCommerce + Dokan or WC Vendors: If you prefer using WordPress, WooCommerce can be extended with marketplace plugins like Dokan or WC Vendors to create a multi-vendor system. It provides flexibility and ease of integration with WordPress-based websites.
Sharetribe: A platform for creating marketplaces that offer flexibility in design and features. It supports various business models, including B2B2C, and offers a simplified approach for smaller businesses.
Arcadier: A marketplace platform that enables businesses to create multi-vendor platforms. Arcadier offers a variety of customizable features, but it may lack some of the enterprise-grade features found in Mirakl or BigCommerce.
Factors to Consider When Choosing a Platform:
Scalability: Make sure the platform can scale as your business and the number of vendors grow.
Customization: Does the platform allow you to customize the look and feel of each vendor's storefront? Does it provide flexibility for the backend (e.g., order management)?
Payment Handling: Can the platform efficiently handle vendor commissions and payments? Does it support different payment gateways?
Vendor Support and Management: How easy is it for vendors to manage their product catalogs, orders, and fulfillment?
Integration Capabilities: Ensure that the platform integrates well with your existing systems (ERP, CRM, shipping carriers).
Cost: Consider the long-term costs (subscriptions, apps, transaction fees) of the platform. Some platforms may offer lower upfront costs but may have higher transaction or subscription fees as your business grows.
Final Recommendations:
If you're looking for an enterprise-grade solution with robust marketplace features, Mirakl is the best option. It can handle complex workflows and large numbers of vendors.
If you're looking for something more affordable and user-friendly, BigCommerce or Shopify (with the right apps) might be a good fit. Shopify is excellent for a more hands-off approach with third-party apps, while BigCommerce can offer a more built-in, integrated solution for multi-vendor marketplaces.
For more customization and lower upfront costs, WooCommerce with Dokan or WC Vendors is a good option, especially if you're already familiar with WordPress.
Finally, choose a platform that best suits the long-term needs of your mall and its vendors, considering both the vendor experience and customer experience.
If you’re still unsure or need help implementing and customizing these platforms, feel free to contact specialized consultants or developers with experience in e-commerce and multi-vendor marketplace setups.
Many design leaders find themselves in an impossible situation. On
one side, senior management have read articles trumpeting the incredible
ROI of user experience design. McKinsey tells us that design-led companies achieve 56% higher returns to shareholders. Forrester reports that every dollar invested in UX brings 100 dollars in return.
Yet
the reality I encounter when talking to design leaders is very
different. Most are desperately under-resourced, with tiny teams
expected to support hundreds of projects across their organizations. The
result? We’re spread so thin that we can barely scratch the surface of
what needs doing.
The problem isn’t just about resources. It’s about expectations
and how we define our role. Too often, we position ourselves (or are
positioned by others) as implementors — the people who do the user
research, create the prototypes, and run the usability tests. But with
the scale of digital touching every corner of our organizations, that’s
simply not sustainable.
We
need to stop trying to do everything ourselves and instead focus on
empowering others across the organization to improve the user
experience. In other words, we need to become true leaders rather than
just practitioners.
This isn’t about giving up control or lowering standards. It’s about maximizing our impact
by working through others. Think about it: would you rather be directly
involved in 10% of projects or have some influence over 90% of them?
Instead
of trying to be involved in every project, focus on providing specific,
high-value services that can make the biggest impact. This might
include:
Running discovery phases for major initiatives By
strategically initiating discovery phases for critical projects, you
ensure that they start with a strong, user-focused foundation. This can
involve tools like the Strategic User-Driven Project Assessment (SUPA),
which helps validate ideas by assessing audience value, user needs,
feasibility, and risks before committing to major investments. SUPA
ensures projects are not just built right but are the right ones to
build.
Project-Specific UX Guidance Regular
feedback on design assets throughout a project keeps UX principles front
and center. This can be achieved by offering UX audits, periodic
check-ins to assess progress, or design reviews at key milestones.
Facilitating workshops and problem-solving sessions Leading
targeted workshops or brainstorming sessions empowers teams to overcome
design challenges on their own with your guidance. These tailored
sessions help teams understand how to make better user-centered
decisions and solve issues themselves, spreading UX capabilities beyond
your team.
The key is to be strategic about where
you spend your time, focusing on activities that will have the greatest
ripple effect across the organization.
One of the most effective ways to scale your impact is through coaching. This could include:
UX Office Hours Designate
times where anyone in the organization can drop in to get quick UX
advice. This informal setting can solve small issues before they
snowball and helps stakeholders learn as they go.
One-on-One or Group Coaching Scheduled
check-ins with individuals or teams are great opportunities to address
challenges directly, mentor those who need extra support, and ensure
alignment with best practices. Regular 1:1 or group coaching keeps UX
priorities on track and provides valuable guidance when and where it’s
needed most.
Tailored Problem-Solving Sessions Providing
bespoke guidance for specific challenges that teams encounter empowers
them to tackle design obstacles while internalizing the principles of
good UX. These problem-solving sessions can be invaluable in ensuring
teams can autonomously address future problems.
The goal isn’t to turn everyone into UX experts but to help them understand enough to make better decisions in their daily work.
It’s
also important to recognize that others might not initially deliver
work at the same level of quality that you would. This is okay. The
primary goal is to get people engaged and excited about UX. If we
criticize them every time they fall short of perfection, we risk
undermining their enthusiasm. Instead, we need to foster a supportive environment where improvement happens over time.
Develop tools and resources that help others apply UX principles independently. For example:
Design Systems Create and maintain a comprehensive design system
that integrates UX best practices into the UI across the organization. A
well-crafted design system ensures that everyone, from developers to
designers, aligns on consistent best practices, making it easier for
teams to work independently while still maintaining high standards. This
includes reusable code components, clear documentation, and alignment
between design and development.
UX Tool Suite Providing
teams with pre-selected tools for user research, prototyping, and user
testing helps maintain quality and saves time. With tools for everything
from user research to usability testing, you provide the resources
teams need to conduct UX activities on their own without extensive
onboarding.
Research Repository Maintain a
centralized repository of user research findings that can be accessed by
anyone across the organization. A well-organized research repository
can reduce duplication of effort, provide insights across different
initiatives, and allow teams to learn from each other’s findings. This
promotes consistent application of user insights across projects.
Supplier Lists Providing
a vetted list of suppliers and external agencies helps ensure
consistency when work is outsourced. It provides quick access to
high-quality resources, mitigates risk, and builds trust with suppliers
who understand your standards.
Self-Service Training Resources Create
a library of on-demand training materials that teams can access when
needed. This should include video tutorials, interactive exercises, case
studies, and step-by-step guides for common UX tasks like conducting
user interviews, creating personas, or running usability tests. Unlike
scheduled workshops, self-paced learning allows people to access
knowledge exactly when they need it, leading to better retention and
practical application.
These resources should be practical and accessible, making it easy for teams to do the right thing.
Create a framework that guides UX decisions across the organization:
Design Principles Establish
core design principles that align with your organization’s values and
user-centered goals. These principles help ensure consistency and
clarity in decision-making. For example, define around six to ten
principles that stakeholders across the organization have voted on and
agreed upon, ensuring broader buy-in and consistent decision-making.
Policies for UX Develop clear policies that standardize
processes like work requests, user research and testing, and
stakeholder involvement. These policies help set expectations, keep
efforts aligned with organizational goals, and make it easier for non-UX
professionals to understand and comply with best practices.
Project Prioritization Policies Having
clear guidelines on how projects are prioritized ensures that UX gets
the attention it needs in the planning stages, preventing it from being
overlooked or marginalized. Establish policies that align project value
to user needs and organizational priorities.
The
key is to make these standards helpful rather than bureaucratic — they
should enable better work, not create unnecessary obstacles.
All of these elements should come together in what I call a UX Playbook
— a single source of truth that contains everything teams need to
deliver better user experiences. This isn’t just another document to
gather dust; it’s a living resource that demonstrates your value as a
leader and helps others get started on their UX journey.
The
shift from practitioner to leader isn’t easy. It requires letting go of
some control and trusting others to carry forward UX principles. But
it’s the only way to create lasting change at scale.
There
are many ways to elevate a design project from good to incredible. For
web and product designers, it’s not just about adding more animations
and flair. What it truly comes down to is a reframing of your thought
processes starting before the project even kicks off. Olivia De Alba
presents three approaches that designers can implement and which will
change the way they make their projects more successful.
What
makes an incredible project? Is it the client? The type of project? An
exorbitant budget? While those things help to create the environment in
which a great project can thrive, what truly makes a project something
powerful is you.
No, this isn’t some pep talk on
why you are the ultimate weapon — but yes, you are if you want to be. I
am simply a web and product designer writing down my observations in
order to give others the tools to make their project experiences all the
better for it.
Still with me? Let me tell you about what I’ve discovered over the years working as an agency designer.
There are three approaches
that have completely changed the way my projects run from start to
finish. I have found that since implementing all three, my work and my
interactions with clients and coworkers have blossomed. Here they are:
Unlearn previous experiences through Reframing.
Tap into your background with Connection Paths.
Take up your own space. Period.
In
this article, you will find explanations of each approach and connected
practical examples — as well as real-life ones from my project work at
Fueled + 10up — to show you how they can be applied to projects. With
that said, let’s dive in.
Approach 1: Unlearn Previous Experiences Through Reframing #
While
some of the things that we have learned over the years spent in design
are invaluable, amidst those previous experiences, there are also the
ones that hold us back.
Unlearning ingrained lessons is not an
easy thing to do. Rather, I challenge you to reframe them and get into
the habit of asking yourself, “Am I stopping short creatively because I have always gone this far?” or “Am I associating an implied response from others due to a previous experience and therefore not doing enough for the project?”
Let me give you some examples of thoughts that may arise on a given project and how you can reframe them in a better way.
“I’ve designed cards thousands of times. Therefore, there are only so many ways you can do it.”
As
you know, in 99.9% of website design projects, a card design is
required. It may seem that every possible design ever imagined has been
created up to this point — a fair reasoning, isn’t it? However, stifling
yourself from the very get-go with this mentality will only serve to
produce expected and too-well-known results.
Instead, you could approach this scenario with the following reframed thought:
“I’ve
designed cards thousands of times, so let me take what I’ve learned, do
some more exploration, and iterate on what could push these cards
further for this particular project.”
With this new
outlook, you may find yourself digging deeper to pull on creative
threads, inevitably resulting in adaptive thinking. A good exercise to
promote this is the Crazy 8’s design exercise.
In this format, you can pull forth rapid ideas — some good, some not so
good — and see what sticks. This method is meant to get your brain
working through a simple solution by tackling it from multiple angles.
Here
is a real-life example from one of my projects in which I had to
explore cards on a deeper level. This client’s website was primarily
made up of cards of varying content and complexity. In the initial
stages of design, I worked to define how we could differentiate cards,
with prominence in size, imagery, and color, as well as motion and hover
effects.
What I landed on was a flexible system that had three
tiers and harmonized well together. Knowing they had content that they
wanted to be highlighted in a distinctive way, I created a Featured Card
and tied it to the brand identity with the cutout shape in the image
masking. I also included the glass effect on top to allude to the
brand’s science background and ensure the text was accessible. For the Stacked Card,
I introduced a unique hover effect pattern: depending on where the card
was in a given grid, it would determine the card’s hover color. Lastly,
for the Horizontal Card, I wanted to create something that had
equal emphasis on the image and content and that could also stand alone
well, even without an image.
While
these cards include what most cards usually do, the approach I took and
the visual language used was unique to the client. Instead of working
on these too quickly, I ventured down a different path that took a
little more thought, which led me to a result that felt in tune with the
client’s needs. It also pushed me outside of what I knew to be the
standard, straightforward approach.
“Fast is better. Clients and project teams want me to be fast, so it’s okay if I cut down on exploration.”
In
most projects, speed is indeed rewarded. It keeps the project within
its budget constraints, the project managers are happy, and ultimately,
the clients are happy, too. However, what it can end up doing instead is
generating errors in the process and hindering design exploration.
“I
like to work fast because I want the team to be successful. In
addition, I want to make sure I have not only produced high-quality work
but also explored whether this is the best and most creative solution
for the project.”
With this new outlook, you are still
looking out for what clients and project teams want (successful
outcomes), but you have also enriched the experience by fully executing
your design expertise rather than just churning out work.
One recommendation here is to always ensure you are communicating with your project team about the budget and timelines. Keeping yourself aware of these key goals will allow you to pace when to push for more exploration and when to dial it in.
I
experienced this on a project of mine when a client’s piece of feedback
seemed clear-cut, but as we entered a third round of design surrounding
it, it revealed that it was much more complicated.
The client, Cleveland Public Library, had approved a set of wireframes for their homepage that illustrated a very content-heavy hero,
but when it came to the design phase, they were delighted by a simpler,
more bold design for a block that I created in my preliminary design
explorations. At first, I thought it was obvious: let’s just give them a
dialed-in, simple hero design and be done with it. I knew the hours
were precious on this project, and I wanted to save time for later on as
we got into the finer design details of the pages. However, this was an
error on my part.
After taking a step back and removing speed as a
key factor during this phase of the project, I found the solution they
actually needed: a content-heavy hero showcasing the breadth of their
offerings, melded with the boldness of the more pared-down design. And
guess what? This variant was approved instantly!
Now
that I have shown you two examples of how to unlearn previous
experiences, I hope you can see the value of reframing those moments in
order to tap into a more uninhibited and unexplored creative path. Of
course, you should expect that it will take several implementations to
start feeling the shift towards inherent thinking — even I need to remind myself to pause and reframe, like in the last example. Rome wasn’t built in a day, as they say!
I
challenge you to identify a few moments on a recent project where you
could have paused, reflected, and used more creativity. What would you
have done differently?
Approach 2: Tap Into Your Background With Connection Paths #
I
know I just talked about unlearning some of our previous experiences to
unlock creativity, but what about the ones we may want to tap into to
push us even further? Every designer has an array of passions, memories,
and experiences that have culminated into what makes us who we are
today. We often have a work self — professional and poised, and a
personal self — exploding with hobbies. How can we take those unique
facets of our personalities and apply them to our projects?
Creating
connections with projects and clients on a deeper level is a major way
to make use of our personal experiences and knowledge. It can help to
add inspiration where you otherwise may not have found that same spark
on a project or subject matter.
Let me walk you through what I like to call the Three Connection Paths. I’ll also show you how you can pull from these and apply them to your projects.
This connection path is one in which you have overlapping interests with the client or subject matter.
An
example of this is a client from the video game industry, and you play
their video games. Seems like an obvious connection! You can bring in
your knowledge and love for the game industry and their work. You could
propose easter eggs and tie-ins to their games on their website. It’s a
match made in heaven.
This connection path is one in which you cross at a singular point with the client or subject matter.
An
example of this is a client, which is a major restaurant chain, and you
used to work in the food industry. With your background, you understand
what it is like to work at a restaurant, so you might suggest what CTA’s or fun graphics would be important for a staff-centric site.
This connection path is one in which you are tethered to the client or subject matter through who you know.
An
example of this is a client in the engineering field, and one of your
family members is an engineer. You can then ask your family members for
insights or what would be a good user experience for them on a
redesigned website.
Sometimes,
you won’t be so lucky as to align with a client in one of the Three
Connection Paths, but you can still find ways to add a layered
experience through other means, such as your skillset and research. In
the last example, say you know nothing about engineering nor have a
connection to someone who does, but you are an excellent copy editor
outside of work. You can propose tweaking the verbiage on their hero
section to emphasize their goals all the more. This shows care and
thoughtfulness, giving the client an experience they are sure to
appreciate.
A real-life example in which I implemented a Direct Connection Path on a project was for Comics Kingdom’s website
redesign. When I was younger, I wanted to be a manga creator, so this
client being an intermediary between comic readers and creators
resonated with me. Not only that, but I still practice illustration, so I
knew I had to bring this skill set to the table, even though it was not
part of the original scope of work.
I allowed myself to lean into
that spark I felt. I hand-sketched a few illustrations in Procreate for
their website that felt personal and tied to the joy that comics evoke.
Beyond that, I found a way to incorporate my knowledge of manga into a
background pattern that pulled inspiration from nawa-ami (a
traditional cross-hatching style to denote deep thought) and mixed it
with the motif of fingerprints — the idea of identity and the artist’s
own mark on their work.
Due
to my deep passion, I was able to cultivate an excellent collaborative
relationship with the client, which led to a very successful launch and
being invited to speak on their podcast.
This experience solidified my belief that through tapping into
Connection Paths, you can forge not only amazing projects but also
partnerships.
Look
at what projects you currently have and see which of the Three
Connection Paths you could use to build that bond with the client or the
subject matter. If you don’t see one of the Three Connection Paths
aligning, then what skills or research could you bring to the table
instead?
The
last — and arguably most important — approach to leveling up your
projects is taking up your own space. I’m not referring to physical
space like strong-arming those around you. What I’m referring to is the
space in which designers take to be vocal about their design decisions.
A
lot of designers find this practice uncomfortable. Whether it stems
from having not been given that space to practice as a beginner
designer, higher ranking designers not leaving the room for those less
vocal, or even you yourself feeling like someone else might be better
suited to talk to a particular point.
Similarly,
some designers find themselves retreating when receiving feedback.
Instead of standing behind the reasoning of their designs or asking
follow-up questions, it seems easier to simply go along with the
requested change in order to make the client or team member providing
the feedback happy. Even if you disagree with the request, does it feel
like you need to execute it just because the client — or someone you feel outranks you — told you to?
Illuminating
your opinions and reasoning in conversations is what will get those
around you to trust in your decisions. Hiding them away or conceding to
client whims isn’t going to show those around you that you have the
knowledge to make the proper recommendations for a project.
Now,
I’m not saying that you will need to always disagree with the provided
feedback to show that you have a backbone. Far from it. I think there is
a time and place for when you need to lean into your expertise, and a
time and place for when you need to find a middle ground and/or
collaborate. Collaborating with coworkers and clients lets them peek
into the “why” behind the design decisions being made.
A great example of this is a client questioning you on a particular font size, saying it feels too large and out of place.
You have two options:
You could say that you will make it smaller.
Or you could dig deeper.
If
you have been paying attention thus far, you’d know that option 2. is
the route I would suggest. So, instead of just changing the font size,
you should ask for specifics. For example, is the type hierarchy feeling
off — the relationship of that heading to the body font it is paired
with? You can ask if the size feels large in other instances since
perhaps this is your H2 font, so it would need to be changed across the
board. Calling attention to why you chose this size using data-informed
UX design, accessibility, brand, or storytelling reasons all amplify
your decision-making skills before the client, so including that
information here helps.
If, after the discussion, the client still
wants to go with changing the font size, at least you have given your
reasoning and shown that you didn’t thoughtlessly make a decision — you
made the design choice after taking into consideration multiple factors
and putting in a lot of thought. Over time, this will build trust in you
as the design expert on projects.
An example in which I showcased taking up my own space was from a recent project I worked on for Hilton Stories in their collaboration with Wicked.
After conceptualizing a grand takeover experience complete with a
storytelling undertone, one of the clients wanted to remove the
page-loading animation with the idea of having more branded elements
elsewhere.
While most of my team was ready to execute this, I read
between the lines and realized that we could solve the issue by
including clear verbiage of the collaboration on the loading animation
as well as adding logos and a video spot to the interior pages. By
sticking up for a key piece of my designs, I was able to show that I was
aligned with not only my design decisions but the major goals of the
project. This solution made the clients happy and allowed for a
successful launch with the loading animation that the Fueled + 10up team and I worked so hard on.
The
next time you receive feedback, pause for a moment. Take in carefully
what is being said and ask questions before responding. Analyze if it
makes sense to go against the design decisions you made. If it doesn’t,
tell the client why. Have that open dialogue and see where you land.
This will be uncomfortable at first, but over time, it will get easier.
Now
that you have learned all about the three approaches, there is nothing
stopping you from trialing these on your next project. From unlearning
previous experiences through Reframing to tapping into your background
with Connection Paths, you can lay the groundwork for how your past can
be used to shape your future interactions. When taking up your own
space, start small as you begin to advocate for your designs, and always
try to connect to the “whys” so you instill trust in your clients and
members of your design team.
As Robin Williams so eloquently delivered in the Dead Poets Society, “No matter what anybody tells you, words and ideas can change the world.” In this case, you don’t need to apply it so widely as the entire world, maybe just to your workplace for now.
It’s
been 10 years since scroll-driven animations were introduced in a spec
proposal, and after five years in development, we’re finally beginning
to see pop up in websites. There are scrolly-telling and maze games as well as cover flow animations and 3D rotation with scroll… but what exactly is new here? It’s not like we haven’t seen scroll animations before, but what we have now requires no JavaScript, no dependencies, no libraries — just pure CSS. And if that’s not exciting enough, these animations run off the main thread, delivering smooth, high-performance, GPU-accelerated experiences.
You
can safely use scroll-driven animations in Chrome as of December 2024.
Firefox supports them, too, though you’ll need to enable a flag. Safari?
Not yet, but don’t worry — you can still offer a seamless experience
across all browsers with a polyfill. Just keep in mind that adding a polyfill involves a JavaScript library, so you won’t get the same performance boost.
There
are plenty of valuable resources to dive into scroll-driven animations,
which I’ll be linking throughout the article. My starting point was Bramus’ video tutorial, which pairs nicely with Geoff’s in-depth notesGraham that build on the tutorial.
In this article, we’ll walk through the latest published version by the W3C and explore the two types of scroll-driven timelines — scroll progress timelines and view progress timelines.
By the end, I hope that you are familiar with both timelines, not only
being able to tell them apart but also feeling confident enough to use
them in your work.
Note: All demos in this article only work in Chrome 116 or later at the time of writing.
Scroll Progress Timelines
The
scroll progress timeline links an animation’s timeline to the scroll
position of a scroll container along a specific axis. So, the animation
is tied directly to scrolling. As you scroll forward, so does the
animation. You’ll see me refer to them as scroll-timeline animations in addition to calling them scroll progress timelines.
Just as we have two types of scroll-driven animations, we have two types of scroll-timeline animations: anonymous timelines and named timelines.
Let’s start with a classic example: creating a scroll progress bar at the top of a blog post to track your reading progress.
In this example, there’s a <div>
with the ID “progress.” At the end of the CSS file, you’ll see it has a
background color, a defined width and height, and it’s fixed at the top
of the page. There’s also an animation that scales it from 0 to 1 along the x-axis — pretty standard if you’re familiar with CSS animations!
The progressBar
animation runs once and lasts one second with a linear timing function.
Linking this animation scrolling is just a single line in CSS:
animation-timeline:scroll();
No
need to specify seconds for the duration — the scrolling behavior
itself will dictate the timing. And that’s it! You’ve just created your
first scroll-driven animation! Notice how the animation’s direction is
directly tied to the scrolling direction — scroll down, and the progress
indicator grows wider; scroll up, and it becomes narrower.
In a scroll-timeline animation, the scroll() function is used inside the animation-timeline property. It only takes two parameters: <scroller> and <axis>.
<scroller> refers to the scroll container, which can be set as nearest (the default), root, or self.
<axis> refers to the scroll axis, which can be block (the default), inline, x, or y.
In
the reading progress example above, we didn’t declare any of these
because we used the defaults. But we could achieve the same result with:
animation-timeline:scroll(nearest block);
Here, the nearest scroll container is the root scroll of the HTML element. So, we could also write it this way instead:
animation-timeline:scroll(root block);
The block
axis confirms that the scroll moves top to bottom in a left-to-right
writing mode. If the page has a wide horizontal scroll, and we want to
animate along that axis, we could use the inline or x values (depending on whether we want the scrolling direction to always be left-to-right or adapt based on the writing mode).
We’ll dive into self and inline in more examples later, but the best way to learn is to play around with all the combinations, and this tool by Bramus lets you do exactly that. Spend a few minutes before we jump into the next property associated with scroll timelines.
The animation-range Property
The animation-range for scroll-timeline
defines which part of the scrollable content controls the start and end
of an animation’s progress based on the scroll position. It allows you
to decide when the animation starts or ends while scrolling through the
container.
By default, the animation-range is set to normal, which is shorthand for the following:
This translates to 0% (start) and 100% (end) in a scroll-timeline animation:
animation-range: normal normal;
…which is the same as:
animation-range: 0% 100%;
You can declare any CSS length units or even calculations. For example, let’s say I have a footer that’s 500px
tall. It’s filled with banners, ads, and related posts. I don’t want
the scroll progress bar to include any of that as part of the reading
progress. What I want is for the animation to start at the top and end 500px before the bottom. Here we go:
animation-range: 0% calc(100% - 500px);
Just like that, we’ve covered the key properties of scroll-timeline animations. Ready to take it a step further?
Named scroll-timeline
Let’s say I want to use the scroll position of a different scroll container for the same animation. The scroll-timeline-name
property allows you to specify which scroll container the scroll
animation should be linked to. You give it a name (a dashed-ident, e.g.,
--my-scroll-timeline) that maps to the scroll container
you want to use. This container will then control the animation’s
progress as the user scrolls through it.
Next, we need to define the scroll axis for this new container by using the scroll-timeline-axis, which tells the animation which axis will trigger the motion. Here’s how it looks in the code:
.my-class{/* This is my new scroll-container */scroll-timeline-name: --my-custom-name;scroll-timeline-axis: inline;}
If you omit the axis, then the default block value will be used. However, you can also use the shorthand scroll-timeline property to combine both the name and axis in a single declaration:
.my-class{/* Shorthand for scroll-container with axis */scroll-timeline: --my-custom-name inline;}
I
think it’s easier to understand all this with a practical example.
Here’s the same progress indicator we’ve been working with, but with
inline scrolling (i.e., along the x-axis):
We have two animations running:
A progress bar grows wider when scrolling in an inline direction.
The container’s background color changes the further you scroll.
In this case, the gallery-scroll-container has horizontal scrolling and changes its background color as you scroll. Normally, we could just use animation-timeline: scroll(self inline) to achieve this. However, we also want the gallery-progress element to use the same scroll for its animation.
The gallery-progress element is the first inside gallery-scroll-container,
and we will lose it when scrolling unless it’s absolutely positioned.
But when we do this, the element no longer occupies space in the normal
document flow, and that affects how the element behaves with its parent
and siblings. We need to specify which scroll container we want it to
listen to.
That’s where naming the scroll container comes in handy. By giving gallery-scroll-container a scroll-timeline-name and scroll-timeline-axis, we can ensure both animations sync to the same scroll:
This
allows both animations (the growing progress bar and changing
background color) to follow the same scroll behavior, even though they
are separate elements and animations.
The timeline-scope Property
What
happens if we want to animate something based on the scroll position of
a sibling or even a higher ancestor? This is where the timeline-scope property comes into play. It allows us to extend the scope of a scroll-timeline beyond the current element’s subtree. The value of timeline-scope must be a custom identifier, which again is a dashed-ident.
Let’s illustrate this with a new example. This time, scrolling in one container runs an animation inside another container:
We can play the animation on the image when scrolling the text container because they are siblings in the HTML structure:
Notice that I haven’t specified the scroll axis, as it defaults to block (vertical scrolling), and that’s the value I want.
Let’s move on to the image inside the sardinas-container. We want this image to animate as we scroll through the scroll-container. I’ve added a scroll-timeline-name to its animation-timeline property:
At this point, however, the animation still won’t work because the scroll-container is not directly related to the images. To make this work, we need to extend the scroll-timeline-name so it becomes reachable. This is done by adding the timeline-scope to the parent element (or a higher ancestor) shared by both elements:
With this setup, the scroll of the scroll-container will now control the animation of the image inside the sardinas-container!
Now that we’ve covered how to use timeline-scope,
we’re ready to move on to the next type of scroll-driven animations,
where the same properties will apply but with slight differences in how
they behave.
View Progress Timelines
We just looked at scroll progress animations. That’s the first type of scroll-driven animation of the two. Next, we’re turning our attention to view progress animations.
There’s a lot of similarities between the two! But they’re different
enough to warrant their own section for us to explore how they work.
You’ll see me refer to these as view-timeline animations in addition to calling them view progress animations, as they revolve around a view() function.
The view progress timeline
is the second type of type of scroll-driven animation that we’re
looking at. It tracks an element as it enters or exits the scrollport
(the visible area of the scrollable content). This behavior is quite
similar to how an IntersectionObserver works in JavaScript but can be done entirely in CSS.
We
have anonymous and named view progress timelines, just as we have
anonymous and named scroll progress animations. Let’s unpack those.
Anonymous View Timeline
Here’s
a simple example to help us see the basic idea of anonymous view
timelines. Notice how the image fades into view when you scroll down to a
certain point on the page:
Let’s say we want to animate an image that fades in as it appears in the scrollport. The image’s opacity will go from 0 to 1. This is how you might write that same animation in classic CSS using @keyframes:
That’s great, but we want the image to fadeIn
when it’s in view. Otherwise, the animation is sort of like a tree that
falls in a forest with no one there to witness it… did the animation
ever happen? We’ll never know!
We have a view() function that makes this a view progress animation with a single line of CSS:
And notice how we no longer need to declare an animation-duration
like we did in classic CSS. The animation is no longer tied by time but
by space. The animation is triggered as the image becomes visible in
the scrollport.
Just like the scroll-timeline property, the view-timeline property accepts parameters that allow for more customization:
animation-timeline:view();
<inset> Controls
when the animation starts and ends relative to the element’s visibility
within the scrollport. It defines the margin between the edges of the
scrollport and the element being tracked. The default value is auto, but it can also take length percentages as well as start and end values.
<axis> This
is similar to the scroll-timeline’s axis parameter. It defines which
axis (horizontal or vertical) the animation is tied to. The default is block, which means it tracks the vertical movement. You can also use inline to track horizontal movement or simple x or y.
Here’s an example that uses both inset and axis to customize when and how the animation starts:
img{animation-timeline:view(20% block);}
In this case:
The animation starts when the image is 20% visible in the scrollport.
The animation is triggered by vertical scrolling (block axis).
With the view()
function, it’s also easy to create parallax effects by simply adjusting
the animation properties. For example, you can have an element move or
scale as it enters the scrollport without any JavaScript:
Using the CSS animation-range
property with view timelines defines how much of an element’s
visibility within the scrollport controls the start and end points of
the animation’s progress. This can be used to fine-tune when the
animation begins and ends based on the element’s visibility in the
viewport.
While the default value is normal, in view
timelines, it translates to tracking the full visibility of the element
from the moment it starts entering the scrollport until it fully leaves.
This is represented by the following:
animation-range: normal normal;/* Equivalent to */animation-range: cover 0% cover 100%;
Or, more simply:
animation-range: cover;
There are six possible values or timeline-range-names:
cover Tracks the full visibility of the element, from when it starts entering the scrollport to when it completely leaves it.
contain Tracks when the element is fully visible inside the scrollport, from the moment it’s fully contained until it no longer is.
entry Tracks the element from the point it starts entering the scrollport until it’s fully inside.
exit Tracks the element from the point it starts, leaving the scrollport until it’s fully outside.
entry-crossing Tracks the element as it crosses the starting edge of the scrollport, from start to full crossing.
exit-crossing Tracks the element as it crosses the end edge of the scrollport, from start to full crossing.
You can mix different timeline-range-names
to control the start and end points of the animation range. For
example, you could make the animation start when the element enters the
scrollport and end when it exits:
animation-range: entry exit;
You
can also combine these values with percentages to define more custom
behavior, such as starting the animation halfway through the element’s
entry and ending it halfway through its exit:
animation-range: entry 50% exit 50%;
Exploring all these values and combinations is best done interactively. Tools like Bramus’ view-timeline range visualizer make it easier to understand.
The new thing is that now we can merge these two animations using the entry and exittimeline-range-names, simplifying it into one animation that handles both cases:
@keyframes slideInOut{/* Animation for when the element enters the scrollport */entry 0%{transform:scale(.8)translateY(100px);opacity: 0;}entry 100%{transform:scale(1)translateY(0);opacity: 1;}/* Animation for when the element exits the scrollport */exit 0%{transform:scale(1)translateY(0);opacity: 1;}exit 100%{transform:scale(.8)translateY(-100px);opacity: 0;}}
entry 0% Defines the state of the element at the beginning of its entry into the scrollport (scaled down and transparent).
entry 100% Defines the state when the element has fully entered the scrollport (fully visible and scaled up).
exit 0% Starts tracking the element as it begins to leave the scrollport (visible and scaled up).
exit 100% Defines the state when the element has fully left the scrollport (scaled down and transparent).
This
approach allows us to animate the element’s behavior smoothly as it
both enters and leaves the scrollport, all within a single @keyframes block.
The concept of using view-timeline
with named timelines and linking them across different elements can
truly expand the possibilities for scroll-driven animations. In this
case, we are linking the scroll-driven animation of images with the
animations of unrelated paragraphs in the DOM structure by using a named view-timeline and timeline-scope.
The view-timeline property works similarly to the scroll-timeline property. It’s the shorthand for declaring the view-timeline-name and view-timeline-axis properties in one line. However, the difference from scroll-timeline
is that we can link the animation of an element when the linked
elements enter the scrollport. I took the previous demo and added an
animation to the paragraphs so you can see how the opacity of the text
is animated when scrolling the images on the left:
This
one looks a bit verbose, but I found it hard to come up with a better
example to show the power of it. Each image in the vertical scroll
container is assigned a named view-timeline with a unique identifier:
This makes the scroll timeline of each image have its own custom name, such as --one for the first image, --two for the second, and so on.
Next,
we connect the animations of the paragraphs to the named timelines of
the images. The corresponding paragraph should animate when the images
enter the scrollport:
However, since the images and paragraphs are not directly related in the DOM, we need to declare a timeline-scope on their common ancestor. This ensures that the named timelines (--one, --two, and so on) can be referenced and shared between the elements:
By declaring the timeline-scope with all the named timelines (--one, —two, --three, --four),
both the images and the paragraphs can participate in the same
scroll-timeline logic, despite being in separate parts of the DOM tree.
We’ve covered the vast majority of what’s currently defined in the CSS Scroll-Driven Animations Module Leve 1 specification
today in December 2024. But I want to highlight a few key takeaways
that helped me better understand these new rules that you may not get
directly from the spec:
Scroll container essentials It
may seem obvious, but a scroll container is necessary for scroll-driven
animations to work. Issues often arise when elements like text or
containers are resized or when animations are tested on larger screens,
causing the scrollable area to disappear.
Impact of position: absolute Using
absolute positioning can sometimes interfere with the intended behavior
of scroll-driven animations. The relationship between elements and
their parent elements gets tricky when position: absolute is applied.
Tracking an element’s initial state The browser evaluates the element’s state before any transformations (like translate)
are applied. This affects when animations, particularly view timelines,
begin. Your animation might trigger earlier or later than expected due
to the initial state.
Avoid hiding overflow Using overflow: hidden can disrupt the scroll-seeking mechanism in scroll-driven animations. The recommended solution is to switch to overflow: clip. Bramus has a great article about this and a video from Kevin Powell also suggests that we may no longer need overflow: hidden.
Performance For
the best results, stick to animating GPU-friendly properties like
transforms, opacity, and some filters. These skip the heavy lifting of
recalculating layout and repainting. On the other hand, animating things
like width, height, or box-shadow can slow things down since they require re-rendering. Bramus mentioned that soon, more properties — like background-color, clip-path, width, and height — will be animatable on the compositor, making the performance even better.
Use will-change wisely Leverage this property to promote elements to the GPU, but use it sparingly. Overusing will-change can lead to excessive memory usage since the browser reserves resources even if the animations don’t frequently change.
The order matters If you are using the animation shorthand, always place the animation-timeline after it.
Progressive enhancement and accessibility Combine media queries for reduced motion preferences with the @supports rule to ensure animations only apply when the user has no motion restrictions, and the browser supports them.
For example:
@media screen and(prefers-reduce-motion: no-preference){@supports((animation-timeline:scroll())and(animation-range: 0% 100%)){.my-class{animation: moveCard linear both;animation-timeline:view();}}}
My
main struggle while trying to build the demos was more about CSS itself
than the scroll animations. Sometimes, building the layout and
generating the scroll was more difficult than applying the scroll
animation. Also, some things that confused me at the beginning as the
spec keeps evolving, and some of these are not there anymore (remember,
it has been under development for more than five years now!):
x and y axes These
used to be called the “horizontal” and “vertical” axes, and while
Firefox may still support the old terminology, it has been updated.
Old @scroll-timeline syntax In the past, @scroll-timeline was used to declare scroll timelines, but this has changed in the most recent version of the spec.
Scroll-driven vs. scroll-linked animations Scroll-driven animations were originally called scroll-linked
animations. If you come across this older term in articles,
double-check whether the content has been updated to reflect the latest
spec, particularly with features like timeline-scope.
Resources
All demos from this article can be found in this collection, and I might include more as I experiment further.
A collection of demos from CodePen that I find interesting (send me yours, and I’ll include it!)
This GitHub repo is where you can report issues or join discussions about scroll-driven animations.