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

Tuesday, June 24, 2025

“Product Kondo”: A Guide To Evaluating Your Organizational Product Portfolio

 It starts with good intentions — a quick fix here, a shiny feature there — and suddenly, your product portfolio’s bursting at the seams. In this guide, we walks you through a “Product Kondo” exercise to declutter, realign, and spark some serious product joy for both your business and your customers.

When building digital products, thinking in terms of single features and urgent client needs can lead to a large portfolio of products with high maintenance costs. At first, this approach makes sense, as you’re offering new value to customers and keeping important clients happy. But, over time, you often end up with a collection of highly bespoke solutions that ignore two key principles:

  1. Your product portfolio should cater to your core customer segments and meet their needs.
  2. Your product portfolio should balance the short-term benefits of bespoke solutions against long-term maintenance costs while aligning with your business strategy.

So the reality often looks like this: large legacy product portfolios have grown over time, and the effort required to clean up is hard to prioritize against other seemingly more pressing topics.

This article highlights the benefits of going through a clean-up exercise and explains how to conduct a “Product Kondo” exercise on your product portfolio. Like Marie Kondo, the Japanese master of cleaning up closets and houses to keep what brings you joy, discard what you no longer need, and organize what you keep into a workable order, this exercise seeks to identify the most valuable items for both your business and your customers. This article discusses the issues with large legacy portfolios and explains how to simplify and organize them into customer-centric portfolios, with stakeholder buy-in throughout the process.

Overflowing Product Cupboards

There are many reasons why an organization might end up with a large legacy product portfolio, which, similar to the cupboards organized by Marie Kondo, is in dire need of a good clean-up. Whether your portfolio is overgrown from crafting bespoke solutions for important enterprise clients (a common B2B scenario), from testing new features with a B2C customer segment, or various other possible reasons, incentive structures chiefly among them — overgrown portfolios are very common. And the problem is they need to not just be developed in the first place, they need to be maintained, and that gets ever more costly and complex over time.

While this might be oversimplified, the general logic holds true: the more bespoke your product portfolio, the harder it is to keep clean and tidy. Or as Marie Kondo would say, “In a messy cupboard, it’s impossible to find the pieces that truly bring you joy.” In this context, joy translates into:

  1. Value for the customer,
  2. Revenue for the business.

If you want to work out how to find that joy in your product portfolio again, this article outlines the practical steps taken for such a “Product Kondo” exercise in a global not-for-profit organization with a large legacy portfolio, including the moment when theory met reality, and the learnings from this effort.

We conducted this clean-up in a globally distributed organization undergoing a wider transformation. For more than 20 years, the organization had been gathering and distributing data in various formats: from raw to modelled data, scores, and advanced data products. However, it had not been focused on customer centricity nor regarded products as strategic differentiators. This meant that key indicators of success for product organizations had never been tracked. So the challenge was to map out and simplify the portfolio with very few indicators available to track product performance (e.g., user analytics data).

So, how do you start understanding where the value lies in your portfolio and what factors are driving this portfolio clean-up in the first place?

As part of the wider organizational transformation, one consideration was to simplify the product portfolio in order to reduce maintenance costs and the technical effort required for a planned migration to a new platform. Another important concern was to align future development with the newly developed business strategy. Therefore, reducing costs and planning for the future were the key drivers.

The “Product Kondo” Portfolio Clean-up

So if you find yourself in a similar situation, where you have a complex legacy portfolio, and where across many years features have been added, but hardly anything has ever been sunset, a “Product Kondo” clean-up, i.e., a cleaning out of your product cupboards, might be what’s needed.

To do that, it’s useful to go in with two ideas:

  • Transparency about the need to simplify;
  • Transparency about how decisions will be made, so teams are on board and able to contribute.

Getting buy-in and building a narrative everyone understands and sees as relevant is crucial when trying to clean up — especially in large companies, where you’ll always find someone who thinks “we need everything,” and the relative importance of different customer segments is unclear, with no accurate portfolio overview in place.

If you’re unclear about the state of your current portfolio, how do you know where to focus next strategically?

Not knowing where the highest value lies in your portfolio and how it all maps out as a whole has another implication: If you don’t know your current status quo, it’s hard to plan ahead and it’s equally hard to get out of the delivery mode many product organizations find themselves in, where you simply build what gets requested, but can’t act as a driver of future growth.

To organize a portfolio in order to define how to handle it going forward, while not having much information to base decisions on, the high-level approach was this:

  1. Define the FOR WHOM (By building a user segmentation matrix).
  2. Establish the STATUS QUO (By auditing previous attempts to map the portfolio).
  3. Agree the HOW (By defining evaluation criteria & prioritisation).
  4. Ensuring BUY-IN (through deep dives with key stakeholders and experts).

Note: Every company is different, especially regarding the information that’s available. So this is not an attempt at building the next framework or providing a one-size-fits-all approach to portfolio organization. Instead, it is a proposed solution for how to approach mapping out your current portfolio to start from a cleaner slate, with your customer segments in mind. These four areas of work should be considered as necessary when attempting a “product kondo” exercise in your own organization.

1. For Whom? Building A User Segmentation Matrix

First things first, if you’re not clear about your primary and secondary customer segments, then this is where to start. If you want teams to be able to focus, it’s crucial to define priorities. Identifying key external user groups/segments, understanding their differences, and assessing their importance to the organization’s overall business success is a great start. Building a user segmentation matrix is a great foundation for prioritizing efforts and aligning services/products around user needs.

Apart from establishing the key jobs-to-be-done, goals, and pain points for each customer segment, it fosters transparency around the following factors:

  • Thinking from a customer perspective.
  • Considering measurable data like user numbers, size of accounts, and revenue.
  • The fact that some user groups are more valuable to an organization than others, hence should be ranked higher in a prioritization effort.

How to define user segments, with different levels of relevance to the organization and its future strategy, is described in more detail here. It was the initial mental model shared across teams prior to starting this portfolio simplification effort.

Next up: Understanding the current status quo and building a “source of truth” of everything considered under the remit of the product organization. Because you need a clear reference point to get started.

2. Status Quo: Auditing And Defining What To Measure

To determine the best approach and size the task ahead, understanding what had been done before was crucial, so as not to reinvent the wheel. It was clear that the organization had a sprawling product catalogue that contained a varied mix of different items, lacking clear definitions and categorization.

The initial audit was about updating the product catalog that had been assembled three years earlier and adding information that would be relevant for assessing relative value. As revenue, user numbers, or development effort had never been tracked, this is where we gathered additional insights on each item from the product owners (POs) responsible.

The assessment criteria were partly taken from the previous effort (criteria 1-9), and further criteria were added to obtain a more holistic picture (criteria 10-15). See the table below.

3. How? Doing The Audit

In order to be transparent about decision-making, it was important to agree on the evaluation criteria and scoring with key stakeholders upfront and ensure every contributor understood that a lack of data would lead to low scores. To that end, we asked all 36 product owners (POs) to submit data for each product under their remit. As the organization had not previously tracked this information, the initial responses were often quite vague, and many cells were left blank.

To increase data quality and make data-based decisions, 1:1 interviews with POs allowed us to answer questions and build out “best guess” assumptions together in cases of missing data.

Note: While not technically perfect, we decided that moving forward with assumptions grounded in subject matter expertise, rather than completely missing data, would be preferable.

Lastly, some inputs like “automation potential” were hard to assess for less technical POs. Our approach here followed the product mindset that while it is important to make data-informed decisions, “done is better than perfect.” So once we had enough confidence in the picture that emerged, we proceeded with scoring in the interest of time.

As a side note regarding data quality: 1. Manually cleaning inputs throughout (e.g., removing duplicates) and 2. following up until clear inputs were provided, helped increase input quality. In addition, predefined ranges led to higher data quality than inputs requiring hard-to-quantify data, like, e.g., expected impact.

3.1. Scoring

Defining the scoring methodology upfront and getting stakeholders to align on the relevance of different criteria transparently was crucial for this work. Particularly keeping in mind that simplifying (in other words, reducing) the portfolio has an immediate impact on various teams, communicating openly about what is being done, how, and why is important, so everyone understands the longer-term goal: to reduce cost, maintenance, and prepare for future growth.

The image below illustrates the three stages that led to the prioritized list and score for each item.

Overview of the Scoring methodology
Image 2: Overview of the Scoring methodology. (Large preview)

The outcome of this stage now ranked the business and user value for each data product, and the initial expectation was that this was the end of the portfolio cleanup. A list of all items ranked by their value to the business, so that, e.g., the bottom half could be cut and the rest migrated to the new technical platform in order of priority.

At least that was the theory, and this is where it met reality.

Dealing With Change Reality

Once the weighted list was ready and the whole portfolio was ranked, it became clear that what was considered the “Product portfolio” in fact consisted of 12 different types of items, and roughly 70% of them could not be considered actual products.

While inside the organization, everything was called a PRODUCT, it became clear that the types of items referred to as “products” were in fact a mixed bag of trackers, tables, graphs, extracts, data sets, dashboards, reports, tools, scoring, and so on. And many low-ranking internal-facing tools enabled highly relevant customer-facing products.

The list was essentially comparing “apples to oranges,” and that meant that simply cutting the bottom half of lower-scoring items would lead to the whole “house of cards” tumbling down, especially as a lot of items had dependencies on each other.

What To Do? #

First and foremost, we worked with leadership to explain the issue of missing categorization in the portfolio and the risks that cutting the lower-scoring half of the list would entail, especially due to the time pressures of the wider ongoing transformation effort.

Next, we proposed to work with key product owners and leaders to help categorize the portfolio correctly, in order to determine how best to handle each item going forward.

We used the following five buckets to enable sorting, with the intention of keeping the “other” category as small as possible.

“Buckets” used for categorization
“Buckets” used for categorization. (Large preview)

Aside from simplifying the terminology used, this categorization meant that each category could be handled differently in terms of future work.

For example, all raw data items would be automated, while the process around “low effort” data items didn’t have to be changed going forward, once it was clear how low the manual effort actually was. Notably, the categorization included a “Sunset/Stop” category to allow stakeholders to already move items there during the deep dives of their own volition, rather than through top-down decision making.

4. Getting Buy-in: Building Product Trees #

To get buy-in and allow for active contributions from subject matter experts, we planned workshops per customer segment (as defined by the user segmentation matrix — the initial starting point). Aside from organizing the portfolio items, these workshops allowed key people to be actively involved and thereby act as advocates for the future success of this work.

Using Miro boards to share all audit findings, goals, and the purpose of the clean-up, we conducted seven workshops overall. With 4–6 participants, we spent 3 hours categorizing all items per customer segment. In order to avoid groupthink, all participants were asked to cluster their part of the portfolio as part of the preparation.

The “product tree” concept, developed as an innovation game called “prune the product tree” by Luke Hohmann to organize features around customer needs, helped create a shared mental model among participants. In contrast to Hohmann, we applied the product tree concept here to organize the current portfolio logically and actively reduce it, rather than imagine new products.

In this context, the roots of the tree signified raw data, the tree trunk equated to modeled or derived data, with the crown of the tree signifying data products, and the outer branches were left for “other” items — to capture what could not be easily grouped but had to be included.

Product tree metaphor for categorization
Product tree metaphor for categorization. (Large preview)

Grouping items in this way served a second purpose: to guide how to handle them in the future transformation effort. The plan was to automate raw data first, based on priority. While modeled or derived data would have to be checked for complexity to determine future handling. The actual data products identified would be crucial for the company’s future strategy and were to be reimagined with a product mindset going forward.

The tree metaphor worked well here, despite being used in a different way from its original context, as it provided a mental model for categorization. By clustering items, it was possible to better determine their value for each customer segment in the portfolio. According to the feedback gathered after each workshop, the joint mapping and visualization helped teams trust the process and feel actively involved.

Findings #

Analyzing the findings from the workshops revealed the complexity of this effort, with many different factors playing into the prioritization. To visualize this complexity, we used the following approach:

  • Mapping out the product tree by swimlanes (as introduced in the workshops).
  • Layering in usage across multiple segments (through color-coding).
  • Adding the level of dependencies (through the type of frame around each item).
  • Then, add the quantitative assessment and ranking through numbering and color-coding.

For each workshop, we cleaned up the boards, making sure to include crucial comments, especially those about future treatment, such as when a legal obligation to deliver would end.

Product tree example
Organizing data items into swimlanes, following the product tree metaphor. (Large preview)

Using swimlanes helped participants organize data items, while the tree metaphor clarified the interconnectedness and dependencies between items. Especially in the context of data products, this makes a lot of sense, e.g., with raw data being at the root of all other possible versions of “products” derived from them, whether these might be scores, modelled data, automated reports, or more advanced products.

Doing this Product Kondo exercise also helped the teams and all stakeholders gain a shared understanding of how the portfolio was structured for each customer segment. The visualization in swimlanes and with colour-coding and various different frames provided a way to illustrate the complex reality that the initial ranked list format wasn’t able to clarify.

Only once this portfolio mapping was in place, and once quantitative as well as qualitative insights were combined, was it possible to make good decisions about how to handle each item going forward.

For example, all items in the “raw data” category would be automated as part of the wider transformation effort, while all items in the “sunset” category would definitely not be considered for migrating over to the new tech platform. Moreover, the items grouped under “low effort” would continue to be handled manually, while all items grouped under “derived & modelled” would have to be assessed further by a team of tech leads to determine whether or not they might be automated in the future. The items most relevant for the future business strategy of this organization were those grouped under “data products”, i.e., those products that would have to be re-imagined with clear customer needs in mind, based on the user segmentation matrix.

Learnings

In total, we achieved a portfolio reduction of 67.8% from 198 items initially to 118 post clean-up. However, what matters here is not simply the reduction but the categorization, i.e., separating and organizing the portfolio into different swimlanes and introducing the product tree metaphor. The product tree visualisation helped all stakeholders understand the interconnectedness of the portfolio, where the roots signify the core product and the branches different, more advanced products or features built on top of that core.

Similarly, the categorization into swimlanes helped to organize and cluster similar items, getting away from comparing apples and oranges in the initial big portfolio audit table. It illustrated very clearly that not all items are alike and can’t be judged and rated in the same way.

It is worth mentioning that there is no one best way to label your swimlanes, but a good starting point is to think of naming different clusters, e.g., from basic to most complex, and to always include a “sunset/stop” cluster and potentially one that covers “redesign/tech upgrade” items. Having these two buckets allows contributors to actively shape the decision-making around the quick-win items, usually the most obviously outdated or clunky parts of the portfolio.

Whether or not you categorize your products in order to determine how to handle them in an organizational transformation, e.g., to assess automation potential, will largely depend on why and when you’re cleaning up your product portfolio. Even outside of a transformation effort, clustering your portfolio into different categories, understanding interconnectedness, and whether or not each customer segment has a well-rounded product tree, with solid roots and future-looking branches, is a useful exercise in sense-making and keeping your organization lean.

Product Kondo outcomes
Product Kondo outcomes. (Large preview)

Shared Terminology Matters #

In all this, our biggest learning was that

Terminology matters because simply referring to things as “products” doesn’t make them so. Comparing like for like is a key factor when assessing a product portfolio.

Correct categorization was the biggest challenge that had to be dealt with first, to enable the organization to iterate and focus on where to play and re-imagine products to match the future business strategy.

When Theory Meets Reality #

This portfolio clean-up had to pivot and expand to include a mapping exercise because we hadn’t factored in the unclear terminology used across the organization, and that, instead of simply gathering and ranking, the biggest task was to correctly categorize and structure. And this is likely to be different from organization to organization. So I would always recommend checking which categories of items you’re comparing in your portfolio. If you’re not entirely sure, you should always include a clustering or mapping exercise right from the start.

Product Kondo: The Groundwork For Transformation

If you’re struggling with a large legacy portfolio and no longer confident that everything in it serves a purpose and brings joy to users and the business, it’s time to clean up.

It’s often necessary and needed to focus on the next shiny thing, but if you don’t balance that with cleaning up your existing portfolio, your organization will eventually become slow. Overgrown product portfolios can’t be sustained forever.

Particularly in organizations bound by various contractual obligations, this is the groundwork that enables product teams to iterate.

Moreover, doing this clean-up and clearing out effort across teams is a highly transparent way to include teams in change. And it is a useful way for getting teams to contribute and actively shape a transformation effort. Business decisions have to be taken, but taking them with transparency and in an evidence-guided way ensures that you are bringing people along.

Product Kondo benefits include the following: Focus, Impact, Decision making, Clean slate, Consistency, End-to-end
Benefits of cleaning up your portfolio. (Large preview)

Last but not least — if you don’t have the capacity to do the full portfolio clean-up (which took us about 4 months, with a core team of roughly 4 people) — start smaller. And start with including these considerations in your day-to-day, for example, by always checking if products or features should be stopped or sunset every time you’re launching new products. Or start by mapping out the different categories of items in your portfolio — with swimlanes and the product tree metaphor in mind. What is core, and what is the future state of play?

Upside: Once you’ve got that big picture overview and worked out what to sunset or where to slim down, you have more capacity to focus on current and future priorities strategically.

Reality check: Of course, the work doesn’t stop there. The next step is to align it all back to your user segments and check how your portfolio serves each of these, particularly the primary segments.

Further Reading

Monday, June 23, 2025

Integrating Localization Into Design Systems

 

Learn how two designers tackled the challenges of building a localization-ready design system for a global audience. This case study dives into how Rebecca and Mark combined Figma Variables and design tokens to address multilingual design issues, such as text overflow, RTL layouts, and font inconsistencies. They share key lessons learned and the hurdles they faced — including Figma’s limitations — along with the solutions they developed to create dynamic, scalable designs that adapt seamlessly across languages, themes, and densities. If you’re navigating the complexities of internationalization in design systems, this article is for you.

Mark and I work as product designers for SAS, a leader in analytics and artificial intelligence recognized globally for turning data into valuable insights. Our primary role is to support the token packages and component libraries for the SAS Filament Design System. SAS’ customer base is global, meaning people from diverse countries, cultures, and languages interact with products built with the Filament Design System.

SAS designers use Figma libraries developed by the Filament Design System team to create UX specifications. These high-fidelity designs are typically crafted in English, unknowingly overlooking multilingual principles, which can result in layout issues, text overflow, and challenges with right-to-left (RTL) languages. These issues cascade into the application, ultimately creating usability issues for SAS customers. This highlights the need to prioritize localization from the start of the design process.

With the introduction of Figma Variables, alongside the advancements in design tokens, we saw an opportunity for designers. We imagined a system where a Figma design could dynamically switch between themes, densities, and even languages.

This would allow us to design and test multilingual capabilities more effectively, ensuring our design system was both flexible and adaptable.

While researching localization integration for design systems, we realized a significant gap in existing documentation on supporting localization and internationalization in design tokens and Figma Variables. Many of the challenges we faced, such as managing typography across locales or adapting layouts dynamically, were undocumented or only partially addressed in available resources.

Our story demonstrates how combining foundational principles of multilingual design with design tokens can help tackle the complexities of language switching in design systems. We are not arguing that our approach is the best, but given the lack of documentation available on the subject, we hope it will get the conversation started.

But before we start, it’s essential to understand the distinction between Localization (L10n) and Internationalization (I18n).

Localization (L10n) refers to the process of adapting designs for specific languages, regions, or cultures and involves the following:

  • Translating text;
  • Adjusting layouts to accommodate language-specific requirements, such as longer or shorter text strings or right-to-left (RTL) text for languages like Arabic;
  • Ensuring visual elements are culturally appropriate and resonate with the target audience.

Internationalization (I18n) is the preparation phase, ensuring designs are flexible and adaptable to different languages and regions. Key considerations in Figma include:

  • Using placeholder text to represent dynamic content;
  • Setting up constraints for dynamic resizing to handle text expansion or contraction;
  • Supporting bi-directional text for languages that require RTL layouts.

These concepts are not only foundational to multilingual design but also integral to delivering inclusive and accessible experiences to global users.

Pre-Figma Setup: Building A Framework

Understanding Our Design Token System

Before diving deeper, it’s crucial to understand that our design tokens are stored in JSON files. These JSON files are managed in an application we call “Token Depot,” hosted on our corporate GitHub.

We utilize the Tokens Studio plugin (pro plan) to transform these JSON files into Figma libraries. For us, design tokens are synonymous with variables — we don’t create additional variables that only exist in Figma. However, we do create styles in Figma that serve as “recipe cards” for specific HTML elements. For instance, an H2 might include a combination of font-family, font-size, and font-weight.

It’s important to note that our design token values are directly tied to CSS-based values.

Initial Setup: Theme Switching And Localization

In 2022, we took on the massive task of refactoring all our token names to be more semantic. At that time, we were only concerned with theme switching in our products.

Our tokens were re-categorized into the following groups:

  • Color
    • Brand colors (SAS brand colors)
    • Base colors (references to Brand colors)
  • Typography (e.g., fonts, spacing, styles)
  • Space (e.g., padding, margins)
  • Size (e.g., icons, borders)
  • Style (e.g., focus styles)
  • Motion (e.g., animations)
  • Shadow.

In our early setup:

  • A core folder contained JSON files for values unaffected by theme or brand.
  • Brand folders included three JSON files (one for each theme). These were considered “English” by default.
  • A separate languages folder contained overrides for other locales, stacked on top of brand files to replace specific token values.

Our JSON files were configured with English as the default. Other locales were managed with a set of JSON files that included overrides for English. These overrides were minimal, focusing mainly on font and typography adjustments. For example, bold typefaces often create issues because many languages like Chinese, Japanese, or Korean (CJK languages) fonts lack distinct bold versions. Thus, we replaced the font-weight token value from 700 to 400 in our CJK locales.

We also update the values for font-family, letter spacing, font-style, and font-variant tokens. In Figma, our application screens were originally designed in English, and in 2023, we only implemented theme-switching modes, not language options. Additionally, we created detailed lists to document which design tokens could be converted to Figma variables and which could not, as the initial release of variables supported only a limited set.

Introducing Density Switching

The introduction of density switching in our products marked a significant turning point. This change allowed us to revisit and improve how we handled localization and token management. The first thing we had to figure out was the necessary token sorting. We ended up with the following list:

Tokens Impact By Theme And Density

Unaffected by Theme or Density:

  • Color
  • Brand colors
  • Base colors
  • Motion
  • Shadow
  • Size
  • Border size
  • Outline size
  • Typography
  • Base font size
  • Letter spacing and word spacing
  • Overflow, text, and word style tokens.

Tokens Impacted by Density:

  • Typography
  • Font sizes
  • Line Height
  • Font spacing
  • Size
  • Border radius
  • Icon sizes
  • Space
  • Base spacing.

Tokens Impacted by Theme:

  • Colors
  • Action, body, container, dataviz, display, heading, highlight, icon, label, status, syntax, tag, text, thumbnail, and zero-stat
  • Size
  • Border size
  • Typography
  • Font-family
  • Style
  • Action (focus styles).

With density, we expanded locale-specific value changes beyond font-family, letter spacing, font-style, and font-variant tokens to additionally include:

  • Font sizes
  • Icon sizes
  • Line height
  • Spacing
  • Border radius.

Revisiting our type scale and performing numerous calculations, we documented the required token value changes for all the locales across the density. This groundwork enabled us to tackle the restructuring of our JSON files effectively.

JSON File Restructuring

In our token repository, we:

  1. Updated the tokens in the core folder.
  2. Added a density folder and a language folder in each brand.

After collaborating with our front-end development team, we decided to minimize the number of JSON files. Too many files introduce complexity and bugs and hinder performance. Instead of creating a JSON file for each language-density combination, we defined the following language categories:

Language Categories

  • Western European and Slavic Languages
    • Polish, English, French, German, and Spanish
  • Chinese Languages
    • Simplified and traditional scripts
  • Middle Eastern and East Asian Languages
    • Arabic, Hebrew, Japanese, Korean, Thai, and Vietnamese
  • Global Diverse
    • Africa, South Asia, Pacific, and Indigenous languages, Uralic, and Turkic groups.

These categories became our JSON files, with one file per density level. Each file contained tokens for font size, icon size, line height, spacing, and border-radius values. For example, all Chinese locales shared consistent values regardless of font-family.

In addition, we added a folder containing JSON files per locale, overriding core values and theme folders, such as font-family.

Figma Setup: Bridging Tokens And Design

Token Studio Challenges

After restructuring our JSON files, we anticipated gaining support for typography variables in the Tokens Studio plugin. Instead, Tokens Studio released version 2.0, introducing a major shift in workflow. Previously, we imported JSON files directly into Figma and avoided pushing changes back through the plugin. Adjusting to the new version required us to relearn how to use the plugin effectively.

Our first challenge was navigating the complexity of the import process. The $metadata.json and $themes.json files failed to overwrite correctly during imports, resulting in duplicate collections in Figma when exporting variables. Despite recreating the required theme structure within the plugin, the issue persisted. To resolve this, we deleted the existing $metadata.json and $themes.json files from the repository before pulling the updated GitHub repo into the plugin. However, even with this solution, we had to manually remove redundant collections that appeared during the export process.

Once we successfully migrated our tokens from JSON files into Figma using the Tokens Studio plugin, we encountered our next challenge.

Initially, we used only “English” and theme modes in Figma, relying primarily on styles since Figma’s early variable releases lacked support for typography variables. Now, with the goal of implementing theme, density, and language switching, we needed to leverage variables — including typography variables. While the token migration successfully brought in the token names as variable names and the necessary modes, some values were missing.

Typography variables, though promising in concept, were underwhelming in practice. For example, Figma’s default line-height multiplier for “auto” was 1.2, below the WCAG minimum of 1.5. Additionally, our token values used line-height multipliers, which weren’t valid as Figma variable values. While a percentage-based line-height value is valid in CSS, Figma variables don’t support percentages.

Our solution involved manually calculating pixel values for line heights across all typography sizes, locale categories, and densities. These values were entered as local variables in Figma, independent of the design token system. This allowed us to implement correct line-height changes for density and locale switches. The process, however, was labor-intensive, requiring the manual creation of hundreds of local variables. Furthermore, grouping font sizes and line heights into Figma styles required additional manual effort due to the lack of support for line-height multipliers or percentage-based variables.

Examples:

  • For CJK locales, medium and low density use a base font size of 16px, while high density uses 18px.
  • Western European and Slavic languages use 14px for medium density, 16px for high, and 12px for low density.

Additional Challenges

  • Figma vs. Web Rendering
    In Figma, line height centers text visually within the text box. In CSS, it affects spacing differently depending on the box model. This mismatch required manual adjustments, especially in light of upcoming CSS properties like leading-trim.
  • Letter-Spacing Issues
    While CSS defaults to “normal” for letter-spacing, Figma requires numeric values. Locale-specific resets to “normal” couldn’t utilize variables, complicating implementation.
  • Font-Family Stacks
    • Example stack for Chinese:
      font-family-primary: 'AnovaUI', '微软雅黑体', 'Microsoft YaHei New', '微软雅黑', 'Microsoft Yahei', '宋体', 'SimSun', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif.

Starting with a Western font ensured proper rendering of Latin characters and symbols while maintaining brand consistency. However, Figma’s designs using only AnovaUI (SAS Brand Custom font) couldn’t preview locale-based substitutions via system fonts, complicating evaluations of mixed-content designs.

Finally, as we prepared to publish our new library, we encountered yet another challenge: Figma Ghosts.

What Are Figma Ghost Variables? #

Figma “ghost variables” refer to variables that remain in a Figma project even after they are no longer linked to any design tokens, themes, or components.

These variables often arise due to incomplete deletions, improper imports, or outdated metadata files. Ghost variables may appear in Figma’s variable management panel but are effectively “orphaned,” as they are disconnected from any meaningful use or reference.

Why They Cause Issues for Designers:

  • Clutter and Confusion
    Ghost variables make the variable list longer and harder to navigate. Designers might struggle to identify which variables are actively in use and which are obsolete.
  • Redundant Work
    Designers might accidentally try to use these variables, leading to inefficiencies or design inconsistencies when the ghost variables don’t function as expected.
  • Export and Sync Problems
    When exporting or syncing variables with a design system or repository, ghost variables can introduce errors, duplicates, or conflicts. This complicates maintaining alignment between the design system and Figma.
  • Increased Maintenance Overhead
    Detecting and manually deleting ghost variables can be time-consuming, particularly in large-scale projects with extensive variable sets.
  • Thematic Inconsistencies
    Ghost variables can create inconsistencies across themes, as they might reference outdated or irrelevant styles, making it harder to ensure a unified look and feel.

Addressing ghost variables requires careful management of design tokens and variables, often involving clean-up processes to ensure only relevant variables remain in the system.

Cleaning Up Ghost Variables

To avoid the issues in our Figma libraries, we first had to isolate ghost variables component by component. By selecting a symbol in Figma and navigating the applied variable modes, we had a good sense of which older versions of variables the symbol was still connected to. We found disconnected variables in the component library and our icon library, which resulted in compounded ghost variables across the system. We found that by traversing the layer panel, along with a fantastic plug-in called “Swap Variables,” we were able to remap all the ghost variables in our symbols.

If we had not completed the clean-up step, designers would not be able to access the overrides for theme, density, and locale.

Designing Symbols For Localization

To ensure Figma symbols support language swapping, we linked all text layers to our new variables, including font-family, font-size, and line height.

We do not use Figma’s variable feature to define text strings for each locale (e.g., English, Spanish, French) because, given the sheer breadth and depth of our Products and solutions, it would simply be too daunting a task to undertake. For us, using an existing plug-in, such as “Translator,” gives us what we need.

After ensuring all text layers were remapped to variables, along with the “Translator” plug-in, we were able to swap entire screens to a new language. This allowed us to start testing our symbols for unforeseen layout issues.

We discovered that some symbols were not supporting text wrapping when needed (e.g., accommodating longer words in German or shorter ones in Japanese). We isolated those issues and updated them to auto-layout for flexible resizing. This approach ensured all our Figma symbols were scalable and adaptable for multilingual support.

Delivering The System

With our component libraries set up to support localization, we were ready to deliver our component libraries to product designers. As a part of this step, we crafted a “Multilingual Design Cheat Sheet” to help designers understand how to set up their application mockups with Localization and Internationalization in mind.

Multilingual Design Cheat Sheet:

  1. General Principles
    • Design flexible layouts that can handle text wrapping and language-specific requirements such as right-to-left orientations.
    • Use real content during design and development to identify localization issues such as spacing and wrapping.
    • Research the cultural expectations of your target audience to avoid faux pas.
  2. Text & Typography
    • Use Filament Design Systems fonts to ensure support of all languages.
    • Avoid custom fonts that lack bold or italic styles for non-Latin scripts like CJK languages.
    • Reserve additional space for languages like German or Finnish.
    • Avoid hardcoded widths for text containers and use auto-layout to ensure long text strings are readable.
    • The Filament Design System tokens adjust line height per language; make sure you are using variables for line-height.
    • Use bold sparingly, as Filament tokens override bold styling in some languages. Instead, opt for alternative emphasis methods (e.g., color or size).
  3. Layout & Design
    • Mirror layouts for RTL languages (e.g., Arabic, Hebrew). Align text, icons, and navigation appropriately for the flow of the language.
    • Use auto-layout to accommodate varying text lengths.
    • Avoid embedding text in images to simplify localization.
    • Allow ample spacing around text elements to prevent crowding.
  4. Language-Specific Adjustments
    • Adapt formats based on locale (e.g., YYYY/MM/DD vs. MM/DD/YYYY).
    • Use metric or imperial units based on the region.
    • Test alignments and flows for LTR and RTL languages.
  5. Localization Readiness
    • Avoid idioms, cultural references, or metaphors that may not translate well.
    • Provide space for localized images, if necessary.
    • Use Figma translation plug-ins to test designs for localization readiness and use real translations rather than Lorem Ipsum.
    • Test with native speakers for language-specific usability issues.
    • Check mirrored layouts and interactions for usability in RTL languages.

Lessons Learned And Future Directions

Lessons Learned

In summary, building a localization-ready design system was a complex yet rewarding process that taught Mark and me several critical lessons:

  • Localization and internationalization must be prioritized early.
    Ignoring multilingual principles in the early stages of design creates cascading issues that are costly to fix later.
  • Semantic tokens are key.
    Refactoring our tokens to be more semantic streamlined the localization process, reducing complexity and improving maintainability.
  • Figma variables are promising but limited.
    While Figma Variables introduced new possibilities, their current limitations — such as lack of percentage-based line-height values and manual setup requirements — highlight areas for improvement.
  • Automation is essential.
    Manual efforts, such as recalculating and inputting values for typography and density-specific tokens, are time-intensive and prone to error. Plugins like “Translator” and “Swap Variables” proved invaluable in streamlining this work.
  • Collaboration is crucial.
    Close coordination with front-end developers ensured that our JSON restructuring efforts aligned with performance and usability goals.
  • Testing with real content is non-negotiable.
    Design issues like text wrapping, RTL mirroring, and font compatibility only became apparent when testing with real translations and flexible layouts.

Future Directions

As we look ahead, our focus is on enhancing the Filament Design System to better support global audiences and simplify the localization process for designers:

  • Automatic mirrored layouts for RTL languages.
    We plan to develop tools and workflows that enable seamless mirroring of layouts for right-to-left languages, ensuring usability for languages like Arabic and Hebrew.
  • Improved figma integration.
    Advocacy for Figma enhancements, such as percentage-based line-height support and better handling of variable imports, will remain a priority.
  • Advanced automation tools.
    Investing in more robust plugins and custom tools to automate the calculation and management of tokens across themes, densities, and locales will reduce manual overhead.
  • Scalable localization testing framework.
    Establishing a framework for native speaker testing and real-world content validation will help us identify localization issues earlier in the design process.
  • Expanding the multilingual design cheat sheet.
    We will continue to refine and expand the cheat sheet, incorporating feedback from designers to ensure it remains a valuable resource.
  • Community engagement.
    By sharing our findings and lessons, we aim to contribute to the broader design community, fostering discussions around integrating localization and internationalization in design systems.

Through these efforts, Mark and I hope to create a more inclusive, scalable, and efficient design system that meets the diverse needs of our global audience while empowering SAS designers to think beyond English-first designs.

Sunday, June 22, 2025

Integrating Design And Code With Native Design Tokens In Penpot

 

The Penpot team is not slowing down on its mission to build a free design tool that not only offers powerful design features but is also well-integrated with code and modern development practices. In its latest release, Penpot, as the first design tool ever, introduces support for native design tokens. Let’s take a closer look at this concept and how you can employ it in your process.

It’s already the fifth time I’m writing to you about Penpot — and what a journey it continues to be! During this time, Penpot’s presence in the design tools scene has grown strong. In a market that recently felt more turbulent than ever, I’ve always appreciated Penpot for their clear mission and values. They’ve built a design tool that not only delivers great features but is also open-source and developed in active dialogue with the community. Rather than relying on closed formats and gated solutions, Penpot embraces open web standards and commonly used technologies — ensuring it works seamlessly across platforms and integrates naturally with code.

Their latest release is another great example of that approach. It’s also one of the most impactful. Let me introduce you to design tokens in Penpot.

Design tokens are an essential building block of modern user interface design and engineering. But so far, designers and engineers have been stuck with third-party plugins and cumbersome APIs to collaborate effectively on design tokens and keep them in sync. It’s high time we had tools and processes that handle this better, and Penpot just made it happen.

About Design Tokens

Design tokens can be understood as a framework to document and organize your design decisions. They act as a single source of truth for both designers and engineers and include all the design variables, such as colors, typography, spacing, fills, borders, and shadows.

The concept of design tokens has grown in popularity alongside the rise of design systems and the increasing demand for broader standards and guidelines in user interface design. Design tokens emerged as a solution for managing increasingly complex systems while keeping them structured, scalable, and extensible.

The goal of using design tokens is not only to make design decisions more intentional and maintainable but also to make it easier to keep them in sync with code. In the case of larger systems, it is often a one-to-many relationship. Design tokens allow you to keep the values agnostic of their application and scale them across various products and environments.

Design tokens create a semantic layer between the values, the tools used to define them, and the software that implements them.

Schema of the design system
(Large preview)

On top of maintainability benefits, a common reason to use design tokens is theming. Keeping your design decisions decoupled means that you can easily swap the values across multiple sets. This allows you to change the appearance of the entire interface with applications ranging from simple light and dark mode implementations to more advanced use cases, such as handling multiple brands or creating fully customizable and adjustable UIs.

Implementation Challenges

Until recently, there was no standardized format for maintaining design tokens — it remained a largely theoretical concept, implemented differently across teams and tools. Every design tool or frontend framework has its own approach. Syncing code with design tools was also a major pain point, often requiring third-party plugins and unreliable synchronization solutions.

However, in recent years, W3C, the international organization responsible for developing open standards and protocols for the web, brought to life a dedicated Design Tokens Community Group with the goal of creating an open standard for products and design tools to handle design tokens. Once this standard gets more widely adopted, it will give us hope for a more predictable and standardized approach to design tokens across the industry.

To make that happen, work has to be done on two ends, both design and development. Penpot is the very first design tool to implement design tokens in adherence to the standard that the W3C is working on. It also solves the problem of third-party dependencies by offering a native API with all the values served in the official, standardized format.

Design Tokens In Practice

To better understand design tokens and how to use them in practice, let’s take a look at an example together. Let’s consider the following user interface of a login screen:

Acme login screen
(Large preview)

Imagine we want this design to work in light and dark mode, but also to be themable with several accent colors. It could be that we’re using the same authentication system for websites of several associated brands or several products. We could also want to allow the user to customize the interface to their needs.

If we want to build a design that works for three accent colors, each with light and dark themes, it gives us six variants in total:

Six variants of a login screen design with three accent colors and light and dark mode options
Six variants of a login screen design with three accent colors and light and dark mode options. (Large preview)

Designing all of them by hand would not only be tedious but also difficult to maintain. Every change you make would have to be repeated in six places. In the case of six variants, that’s not ideal, but it’s still doable. But what if you also want to support multiple layout options or more brands? It could easily scale into hundreds of combinations, at which point designing them manually would easily get out of hand.

This is where design tokens come to the rescue. They allow you to effectively maintain all the variants and test all the possible combinations, even hundreds of them, while still building a single design without repetitive work.

You can start by creating a design in one of the variants before starting to think about the tokens. Having a design already in place might make it easier to plan your tokens’ hierarchy and structure accordingly.

Different layers of the design
(Large preview)

In this case, I created three components: 2 types of buttons and input, and combined them with text layers into several Flex layouts to build out this screen. If you’d like to first learn more about building components and layouts in Penpot, I would recommend you revisit some of my previous articles:

Now that we have the design ready, we can start creating tokens. You can create your first token by heading to the tokens tab of the left sidebar and clicking the plus button in one of the token categories. Let’s start by creating a color.

Creating your first design token in Penpot

To use design tokens effectively, it’s critical to plan their naming and structure well. You might have noticed that when I created a token, Penpot automatically created for me a new set, called Global. All design tokens have to be organized within sets.

I called my first set “primitives,” so I can store literal values such as “blue,” “purple,” or “grey.” To support multiple shades of color, I used numbers, so the final token names I used are, for example, “slate.1” or “slate.10”.

At this point, we can start thinking about handling multiple colors for various themes. To make it easy to switch between tokens, all you have to do is create multiple sets with tokens of the same names. To do that, I split the primitives into two sets, “light” and “dark.” You can nest your token sets by adding slashes into their names.

Creating design token sets in Penpot

In the video above, you can see that I have two sets, light and dark, each with tokens of the same names but different values. At this point, you could already reference your primitive tokens to switch between light and dark values. However, in the future, you might use the same shade of grey for multiple purposes, like border, background, or text. It would be a more maintainable approach to keep these definitions independent.

To achieve that, we need to introduce a second abstraction layer. In this case, I created a new tokens set called “globals” that references the primitives set. All values in “globals” reference other already existing tokens, such as “primitives.”

For globals, I used semantic naming such as “text.muted” or “background.primary” to stress that the token names are agnostic from their literal values. In other words, the “text.muted” name works well for both light and dark modes, the same as “background.primary” works as a token name no matter what brand color is currently in use. For comparison, “text.dark” or “background.blue” would not make sense if we wanted to make them dynamic and be able to switch between different modes and brand colors.

Tokens structure
(Large preview)

In Penpot, you can reference other tokens in token values by wrapping them in curly brackets. So, if you select “slate.1” as your text color, it will reference the “slate.1” value from any other set that is currently active. With the light set active, the text will be black. And with the dark set active, the text will be white.

Creating alias tokens in Penpot

You can apply your global tokens to any layer you want. To do that, select a layer and then right-click a token of your choice. In the context menu, you can select among the values that are compatible with a token. In the case of a color, it will be either fill or stroke.

Applying design tokens to layers in Penpot

Now, if you switch on and off the sets, you can see the design responding to the change. With the light set active, the text appears black, and with the dark set active, the text appears white.

Changing token sets in Penpot

As you probably noticed, more than one set can be active at the same time, even if they contain values of the same names, like light and dark sets. In such a case, a set lowest on the list will override the already defined values. You can think of it as defining variables in any programming language or properties in CSS. The last value of equal specificity is the one that counts.

However, you don’t need to switch the sets on and off manually to test your design’s appearance. To make that easier, Penpot also offers another concept called Themes. Themes are the best way to manage your sets and combine them into functional design choices.

In the case of light and dark mode, I created two themes: “light” and “dark,” under a group called “Mode.” This makes it much clearer how the sets should be used and makes it easier to switch between the predefined options.

Creating themes in Penpot

For each theme, I selected two sets. One that defines the values (“light” or “dark”) and one that is actually used to style the designs (“globals”). Now, you can use the Themes dropdown to quickly switch themes.

At this point, we have two layers of abstraction: primitives (such as basic color shades) and a semantic layer (background, text, and so on). Sometimes, you might need more than that. With this setup, you can easily switch between light and dark mode, but what if you also want to switch between the several brand colors I showed earlier, while still being able to change the mode? For that, we need another theme (let’s call it “Brand”) and another couple of sets under a parent set that would also be called “Brand.” For the latter, I made three options: “Slate,” “Indigo,” and “Purple.” In real-life scenarios, these could be names of brands, products, and so on.

To bring it all together, the brand sets need to reference primitives, while the “globals” set needs to reference “brand” sets. This way, we are creating three different brands, each with its own separate values for light and dark mode.

Tokens structure with primitives and brand sets
(Large preview)

This allows us to switch between brands and modes and test all the possible combinations.

Switching between themes in Penpot

What’s Next?

I hope you enjoyed following this example. If you’d like to check out the file presented above before creating your own, you can duplicate it here.

Colors are only one of many types of tokens available in Penpot. You can also use design tokens to maintain values such as spacing, sizing, layout, and so on. The Penpot team is working on gradually expanding the choice of tokens you can use. All are in accordance with the upcoming design tokens standard.

The benefits of the native approach to design tokens implemented by Penpot go beyond ease of use and standardization. It also makes the tokens more powerful. For example, they already support math operations using the calc() function you might recognize from CSS. It means you can use math to add, multiply, subtract, etc., token values.

Once you have the design token in Penpot ready, the next step is to bring it over to your code. Already today, you can export the tokens in JSON format, and soon, an API will be available that connects and imports the tokens directly into your codebase. You can follow Penpot on LinkedIn, BlueSky, and other social media to be the first to hear about the next updates. The team behind Penpot is also planning to make its design tokens implementation even more powerful in the near future with support for gradients, composite tokens (tokens that store multiple values), and more.

To learn more about design tokens and how to use them, check out the following links:

Conclusion #

By adding support for native design tokens, Penpot is making real progress on connecting design and code in meaningful ways. Having all your design variables well documented and organized is one thing. Doing that in a scalable and maintainable way that is based on open standards and is easy to connect with code &mdahs; that’s yet another level.

The practical benefits are huge: better maintainability, less friction, and easier communication across the whole team. If you’re looking to bring more structure to your design system while keeping designers and engineers in sync, Penpot’s design tokens implementation is definitely worth exploring.

Tried it already? Share your thoughts! The Penpot team is active on social media, or just share your feedback in the comments section below.

Masonry In CSS: Should Grid Evolve Or Stand Aside For A New Module?

 

There were duelling proposals floating around for adding support for masonry-style layouts in CSS. In one corner is a proposal that extends the existing CSS Grid specification. In the other corner is a second proposal that sets up masonry as a standalone module. Well, not until recently. Now, there are three proposals with Apple WebKit’s “Item Flow” as the third option. The first two sides make strong points, and the third one merges them into one, all of which you will learn about in this article.

You’ve got a Pinterest-style layout to build, but you’re tired of JavaScript. Could CSS finally have the answer? Well, for a beginner, taking a look at the pins on your Pinterest page, you might be convinced that the CSS grid layout is enough, but not until you begin to build do you realise display: grid with additional tweaks is less than enough. In fact, Pinterest built its layout with JavaScript, but how cool would it be if it were just CSS? If there were a CSS display property that gave such a layout without any additional JavaScript, how awesome would that be?

Maybe there is. The CSS grid layout has an experimental masonry value for grid-template-rows. The masonry layout is an irregular, flowing grid. Irregular in the sense that, instead of following a rigid grid pattern with spaces left after shorter pieces, the items in the next row of a masonry layout rise to fill the spaces on the masonry axis. It’s the dream for portfolios, image galleries, and social feeds — designs that thrive on organic flow. But here’s the catch: while this experimental feature exists (think Firefox Nightly with a flag enabled), it’s not the seamless solution you might expect, thanks to limited browser support and some rough edges in its current form.

Maybe there isn’t. CSS lacks native masonry support, forcing developers to use hacks or JavaScript libraries like Masonry.js. Developers with a good design background have expressed their criticism about the CSS grid form of masonry, with Rachel highlighting that masonry’s organic flow contrasts with Grid’s strict two-dimensional structure, potentially confusing developers expecting Grid-like behaviour or Ahmad Shadeed fussing about how it makes the grid layout more complex than it should be, potentially overwhelming developers who value Grid’s clarity for structured layouts. Geoff also echoes Rachel Andrew’s concern that “teaching and learning grid to get to understand masonry behaviour unnecessarily lumps two different formatting contexts into one,” complicating education for designers and developers who rely on clear mental models.

Perhaps there might be hope. The Apple WebKit team just sprung up a new contender, which claims not only to merge the pros of grid and masonry into a unified system shorthand but also includes flexbox concepts. Imagine the best of three CSS layout systems in one.

Given these complaints and criticisms — and a new guy in the game — the question is:

Should CSS Grid expand to handle Masonry, or should a new, dedicated module take over, or should item-flow just take the reins?

The State Of Masonry In CSS Today

Several developers have attempted to create workarounds to achieve a masonry layout in their web applications using CSS Grid with manual row-span hacks, CSS Columns, and JavaScript libraries. Without native masonry, developers often turn to Grid hacks like this: a grid-auto-rows trick paired with JavaScript to fake the flow. It works — sort of — but the cracks show fast.

For instance, the example below relies on JavaScript to measure each item’s height after rendering, calculate the number of 10px rows (plus gaps) the item should span while setting grid-row-end dynamically, and use event listeners to adjust the layout upon page load and window resize.

/* HTML */
<div class="masonry-grid">
  <div class="masonry-item"><img src="image1.jpg" alt="Image 1"></div>
  <div class="masonry-item"><p>Short text content here.</p></div>
  <div class="masonry-item"><img src="image2.jpg" alt="Image 2"></div>
  <div class="masonry-item"><p>Longer text content that spans multiple lines to show height variation.</p></div>
</div>
/* CSS */
.masonry-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); /* Responsive columns */
  grid-auto-rows: 10px; /* Small row height for precise spanning */
  grid-auto-flow: column; /* Fills columns left-to-right */
  gap: 10px; /* Spacing between items */
}

.masonry-item {
  /* Ensure content doesn’t overflow */
  overflow: hidden;
}

.masonry-item img {
  width: 100%;
  height: auto;
  display: block;
}

.masonry-item p {
  margin: 0;
  padding: 10px;
}
// JavaScript

function applyMasonry() {
  const grid = document.querySelector('.masonry-grid');
  const items = grid.querySelectorAll('.masonry-item');

  items.forEach(item => {
    // Reset any previous spans
    item.style.gridRowEnd = 'auto';

    // Calculate the number of rows to span based on item height
    const rowHeight = 10; 
    const gap = 10; 
    const itemHeight = item.getBoundingClientRect().height;
    const rowSpan = Math.ceil((itemHeight + gap) / (rowHeight + gap));

    // Apply the span
    item.style.gridRowEnd = `span ${rowSpan}`;
  });
}

// Run on load and resize
window.addEventListener('load', applyMasonry);
window.addEventListener('resize', applyMasonry);

This Grid hack gets us close to a masonry layout — items stack, gaps fill, and it looks decent enough. But let’s be real: it’s not there yet. The code sample above, unlike native grid-template-rows: masonry (which is experimental and only exists on Firefox Nightly), relies on JavaScript to calculate spans, defeating the “no JavaScript” dream. The JavaScript logic works by recalculating spans on resize or content change. As Chris Coyier noted in his critique of similar hacks, this can lead to lag on complex pages.

Also, the logical DOM order might not match the visual flow, a concern Rachel Andrew raised about masonry layouts generally. Finally, if images load slowly or content shifts (e.g., lazy-loaded media), the spans need recalculation, risking layout jumps. It’s not really the ideal hack; I’m sure you’d agree.

Developers need a smooth experience, and ergonomically speaking, hacking Grid with scripts is a mental juggling act. It forces you to switch between CSS and JavaScript to tweak a layout. A native solution, whether Grid-powered or a new module, has to nail effortless responsiveness, neat rendering, and a workflow that does not make you break your tools.

That’s why this debate matters — our daily grind demands it.

Option 1: Extending CSS Grid For Masonry

One way forward is to strengthen the CSS Grid with masonry powers. As of this writing, CSS grids have been extended to accommodate masonry. grid-template-rows: masonry is a draft of CSS Grid Level 3 that is currently experimental in Firefox Nightly. The columns of this layout will remain as a grid axis while the row takes on masonry. The child elements are then laid out item by item along the rows, as with the grid layout’s automatic placement. With this layout, items flow vertically, respecting column tracks but not row constraints.

This option leaves Grid as your go-to layout system but allows it to handle the flowing, gap-filling stacks we crave.

.masonry-grid {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  grid-template-rows: masonry;
}

First off, the grid-masonry style builds on CSS Grid’s familiarity and robust tooling (e.g., DevTools support). As a front-end developer, there’s a chance you’ve played with grid-template-columns or grid-area, so you’re halfway up the learning matrix. Masonry only extends the existing capabilities, eliminating the need to learn a whole new syntax from scratch. Also, Grid’s robust tooling comes along with Chrome DevTools’ grid overlay or Firefox’s layout inspector, removing the need for JavaScript hacks.

Not so fast: there are limitations. Grid’s specifications already include properties like align-content and grid-auto-flow. Stacking masonry on the list risks turning it into a labyrinth.

Then there are the edge cases. What happens when you want an item to span multiple columns and flow masonry-style? Or when gaps between items don’t align across columns? The specs are still foggy here, and early tests hint at bugs like items jumping unpredictably if content loads dynamically. This issue could break layouts, especially on responsive designs. The browser compatibility issue also exists. It’s still experimental, and even with polyfills, it does not work on other browsers except Firefox Nightly. Not something you’d want to try in your next client’s project, right?

Option 2: A Standalone Masonry Module

What if we had a display: masonry approach instead? Indulge me for a few minutes. This isn’t just wishful thinking. Early CSS Working Group chats have floated the idea, and it’s worth picturing how it could improve layouts. Let’s dive into the vision, how it might work, and what it gains or loses in the process.

Imagine a layout system that doesn’t lean on Grid’s rigid tracks or Flexbox’s linear flow but instead thrives on vertical stacking with a horizontal twist. The goal? A clean slate for masonry’s signature look: items cascading down columns, filling gaps naturally, no hacks required. Inspired by murmurs in CSSWG discussions and the Chrome team’s alternative proposal, this module would prioritise fluidity over structure, giving designers a tool that feels as intuitive as the layouts they’re chasing. Think Pinterest but without JavaScript scaffolding.

Here’s the pitch: a display value named masonry kicks off a flow-based system where items stack vertically by default, adjusting horizontally to fit the container. You’d control the direction and spacing with simple properties like the following:

.masonry {
  display: masonry;
  masonry-direction: column;
  gap: 1rem;
}

Want more control? Hypothetical extras like masonry-columns: auto could mimic Grid’s repeat(auto-fill, minmax()), while masonry-align: balance might even out column lengths for a polished look. It’s less about precise placement (Grid’s strength) and more about letting content breathe and flow, adapting to whatever screen size is thrown at it. The big win here is a clean break from Grid’s rigid order. A standalone module keeps them distinct: Grid for order, Masonry for flow. No more wrestling with Grid properties that don’t quite fit; you get a system tailored to the job.

Of course, it’s not all smooth sailing. A brand-new spec means starting from zero. Browser vendors would need to rally behind it, which can be slow. Also, it might lead to confusion of choice, with developers asking questions like: “Do I use Grid or Masonry for this gallery?” But hear me out: This proposed module might muddy the waters before it clears them, but after the water is clear, it’s safe for use by all and sundry.

Item Flow: A Unified Layout Resolution

In March 2025, Apple’s WebKit team proposed Item Flow, a new system that unifies concepts from Flexbox, Grid, and masonry into a single set of properties. Rather than choosing between enhancing Grid or creating a new masonry module, Item Flow merges their strengths, replacing flex-flow and grid-auto-flow with a shorthand called item-flow. This system introduces four longhand properties:

  • item-direction
    Controls flow direction (e.g., row, column, row-reverse).
  • item-wrap
    Manages wrapping behaviour (e.g., wrap, nowrap, wrap-reverse).
  • item-pack
    Determines packing density (e.g., sparse, dense, balance).
  • item-slack
    Adjusts tolerance for layout adjustments, allowing items to shrink or shift to fit.

Item Flow aims to make masonry a natural outcome of these properties, not a separate feature. For example, a masonry layout could be achieved with:

.container {
  display: grid; /* or flex */
  item-flow: column wrap dense;

  /* long hand version */
  item-direction: column;
  item-wrap: wrap;
  item-pack: dense;

  gap: 1rem;
}

This setup allows items to flow vertically, wrap into columns, and pack tightly, mimicking masonry’s organic arrangement. The dense packing option, inspired by Grid’s auto-flow: dense, reorders items to minimise gaps, while item-slack could fine-tune spacing for visual balance.

Item Flow’s promise lies in its wide use case. It enhances Grid and Flexbox with features like nowrap for Grid or balance packing for Flexbox, addressing long-standing developer wishlists. However, the proposal is still in discussion, and properties like item-slack face naming debates due to clarity issues for non-native English speakers.

The downside? Item Flow is a future-facing concept, and it has not yet been implemented in browsers as of April 2025. Developers must wait for standardisation and adoption, and the CSS Working Group is still gathering feedback.

What’s The Right Path?

While there is no direct answer to that question, the masonry debate hinges on balancing simplicity, performance, and flexibility. Extending the Grid with masonry is tempting but risks overcomplicating an already robust system. A standalone display: masonry module offers clarity but adds to CSS’s learning curve. Item Flow, the newest contender, proposes a unified system that could make masonry a natural extension of Grid and Flexbox, potentially putting the debate to rest at last.

Each approach has trade-offs:

  • Grid with Masonry: Familiar but potentially clunky, with accessibility and spec concerns.
  • New Module: Clean and purpose-built, but requires learning new syntax.
  • Item Flow: Elegant and versatile but not yet available, with ongoing debates over naming and implementation.

Item Flow’s ability to enhance existing layouts while supporting masonry makes it a compelling option, but its success depends on browser adoption and community support.

Conclusion

So, where do we land after all this? The masonry showdown boils down to three paths: the extension of masonry into CSS Grid, a standalone module for masonry, or Item Flow. Now, the question is, will CSS finally free us from JavaScript for masonry, or are we still dreaming?

Grid’s teasing us with a taste, and a standalone module’s whispering promises — but the finish line’s unclear, and WebKit swoops in with a killer merge shorthand, Item Flow. Browser buy-in, community push, and a few more spec revisions might tell us. For now, it’s your move — test, tweak, and weigh in. The answer’s coming, one layout at a time.

References