Figma Essentials and Design Handoff (Dev Mode) Guide for Developers
# Overview
Figma is a browser-based UI/UX design tool.
If developers understand Figma as well as designers do, the gap between design and code can shrink a lot.
In the past, designers handed over design drafts as images or PPT files, and developers built the product based on those guides.
This approach causes many problems whenever the guide does not cover some piece of information.
Questions like "What is this color code?" or "I don't know the font size" come up again and again.
Figma can solve these problems.
Developers can check the properties they need, such as colors, spacing, and typography, on their own, and use them for unit conversion or component mapping.
Regardless of the platform, they can also extract assets, understand the design intent, and review changes.
Rather than how to design, this post looks at Figma from the point of view of a developer who reads and interprets designs and turns them into code.
Figma has the following main features.
| Feature | Description |
|---|---|
| Real-time collaboration | Several people edit the same file at the same time |
| Cross-platform | Supports web browsers, macOS, and Windows |
| Version control | Automatic saving and history management |
| Plugin ecosystem | Extend features with a wide range of plugins |
| Free plan | Most features are available even on the free plan |
# Sign-up and plans
You can create an account for free at Figma.
Plans may change, so check the Figma Pricing page.
Broadly speaking, the plans are as follows.
| Plan | Price | Main features |
|---|---|---|
| Starter | $0 | Unlimited personal files, 3 team projects |
| Professional | $3-16/month | Unlimited projects, Dev Mode, branching |
| Organization | $5-55/month | Organization management, SSO, advanced security |
| Enterprise | $5-90/month | Dedicated infrastructure, advanced admin features |
To upgrade to the Organization plan, you need to use a work email address.
You can use Figma right in your web browser, but you can also install the desktop app.
Installing the desktop app has a few advantages.
| - | Web browser | Desktop app |
|---|---|---|
| Installation | Not required | Required |
| Performance | Depends on the browser | More stable |
| Shortcuts | May conflict with browser shortcuts | Dedicated shortcuts |
| Local fonts | Requires a plugin | Detected automatically |
| Tab management | Mixed with browser tabs | Separate window |
# Interface layout
The Figma screen is made up of four main areas.
- Left sidebar: Manage layers, assets, pages, and more
- Canvas: An infinite area for design work
- Right sidebar: Set the properties, design, prototype, and more for the selected element
- Toolbar: Choose tools such as frames, shapes, and text
# Basic elements
Let's look at the core elements that make up a design in Figma.
Once you understand the role and features of each element, such as areas, shapes, and text, it is easier to decide how each element maps to code when you turn a design into code.
# Pages
A Page is a unit that separates canvases within a single Figma file.
You can organize screen designs, components, design systems, and more into separate pages, and you can add or switch pages in the left sidebar.
If you name a page with just the - (hyphen) symbol, a divider appears in the page list.
This is useful for grouping several pages logically.
# Areas
In Figma, the areas that group or arrange elements come in three kinds: Section, Frame, and Group.
Each has a different role and supports different features, so check the main differences in the following table.
| - | Section | Frame | Group |
|---|---|---|---|
| Purpose | Organizing the canvas and other divisions | Core layout of the actual design | Simply bundling several elements into one |
| Colors, effects, etc. | Yes | Yes | - |
| Clip content | Yes | Yes | - |
| Auto layout | - | Yes | - |
| Constraints | - | Yes | - |
| Prototyping | Yes | Yes | - |
| Dev Mode status | Yes | - | - |
# Section
A Section groups several frames into a top-level area and is optimized for dividing work for sharing purposes, such as planning or development.
Child frames inside a section show their names, but child frames inside a frame do not.
In the following image, the whole area on the left is a section, and the one on the right is a frame.
Inside the section, the names of child frames such as Logo, Button, and Icons are shown.
If you use Resize to fit on a section, it resizes to fit its child frames, with padding included.
A frame also resizes, but without padding.
# Frame
A Frame is the core area of a design that makes up UI elements such as screens, cards, and banners.
You usually create frames at any size you like, but you can also pick device sizes such as smartphone, tablet, or desktop from the frame presets in the right sidebar and create one right away.
In a frame, Clip content hides child elements that overflow.
With Constraints, you can set which position a child element follows when the frame size changes.
With Auto Layout, you can make size, alignment, and more respond dynamically to changes in the frame or its child elements.
# Group
A Group is an area that simply bundles elements, and you use it to control several elements at once.
When you resize a group, its child elements resize along with it.
Also, when you change the color of a group, the color of its child elements changes, not the color of the group itself.
# Shapes and basic properties
You can choose from many shapes in the panel.
Among the shapes, rectangles and circles can be built directly in code with the properties (such as border radius) of an HTML <div> or a Compose Box.
On the other hand, complex shapes such as stars or polygons need to be handled as images with <svg> or <vector>, depending on the situation.
When you select a shape, you can control basic properties such as position and layout in the right sidebar.
Position is shown relative to the parent area (section or frame), and you can align, set coordinates, rotate, or flip the element.
Layout refers to the size of the shape.
It uses Fixed width/height by default, but if the parent frame uses auto layout, you can also set a flexible width with Fill container.
It corresponds to px on the web and dp on Android.
In Appearance, you can set Opacity, Corner Radius, and Apply blend mode.
Fill sets the background color of the shape.
You can choose Solid, Linear gradient, Radial gradient, and more, and you can also use an image as a fill.
Stroke sets the border of the shape.
You can set the color, width, and position (inside/center/outside), and you can also choose styles such as dotted or dashed lines.
In Effects, you can add visual effects such as shadows (Drop shadow, Inner shadow) and blurs (Layer blur, Background blur).
In Export, you can export the element in formats such as PNG, JPG, SVG, and PDF.
You can also set scales (1x, 2x, 3x, and so on) to extract assets for several resolutions at once.
# Text
Text is the element for the written characters in a design.
It corresponds to px on the web and sp on Android.
Layout is divided into Auto width, Auto height, and Fixed size.
With auto width, the width adjusts automatically to the text content, and with auto height, the width stays fixed and only the height changes to fit the content.
With fixed size, you set both the width and the height yourself.
In Typography, you can set the font, weight, size, line height, letter spacing, and more.
If the designer defines a Text Style in advance, you can reuse it while keeping the typography consistent.
Stroke adds a border around the outline of each character in the text.
It is mostly used for logos or emphasized text and is rarely used in regular body text.
# Images
You can load a local image, or copy an image from the web and paste it right onto the Figma canvas.
You can also fill a frame or shape with an image.
# Quick selection
When you click an element on the canvas, the top-level frame is selected by default.
To select a deeply nested element, you can double-click repeatedly to go one level deeper each time.
Or, if you click an element while holding the Ctrl(Cmd) key, the lowest element at the clicked point is selected right away instead of the top-level frame.
If you right-click while holding the Ctrl(Cmd) key, a list of all layers that overlap at that point appears.
You can pick the layer you want from the list, which is especially useful when many elements overlap.
# Layers
Layers represent every element on the Figma canvas (frames, shapes, text, images, and more) as a tree structure.
In the layers panel of the left sidebar, you can check and manage the hierarchy and order of each element.
Higher layers are displayed on top.
# Auto layout
Auto Layout is a concept similar to Flex on the web and LinearLayout on Android, and it automatically aligns child elements and manages the gaps between them.
If you click the Toggle auto layout button in the frame's layout, or choose one of Vertical, Horizontal, or Grid (anything except Freeform) in the layout, the frame switches to auto layout automatically.
# Direction and alignment
Choose Vertical or Horizontal to decide the direction in which child elements are arranged.
You can easily change the order of child elements by reordering their layers or dragging them.
You can also set the alignment point for the child elements.
There are nine options in total, from the top left to the bottom right.
With Wrap, the arranged child elements can wrap onto new lines.
# Padding and gap
Padding is the space inside a frame.
By default, you can set Horizontal padding and Vertical padding.
If you click the individual padding button on the right, you can also set Left padding, Top padding, Right padding, and Bottom padding separately.
With Horizontal gap between objects, you can set the gap between the child elements of a frame.
If you use Wrap to wrap lines, you can also use Vertical gap between rows.
# Sizing
There are three ways to control the size of child elements in a frame with auto layout.
Fixed width/height: Keeps the size you setHug contents: Shrinks to fit its children / hugs its childrenFill Container: Stretches to fit its parent / fills its parent
When a sizing option is applied, a Hug or Fill tag appears in the size field of that element, as follows.
# Constraints
When the size of a parent frame without auto layout changes, you can use Constraints to set which position a child element follows.
Because constraints set an absolute position, you cannot use them on child elements that are arranged inside a parent frame with auto layout.
You can choose from the following values.Left and Top are the default values.
- Horizontal
Left: Pinned to the left of the parentRight: Pinned to the right of the parentLeft+Right: Pinned to both the left and right of the parent, and its width changes as the parent's width changes
- Vertical
Top: Pinned to the top of the parentBottom: Pinned to the bottom of the parentTop+Bottom: Pinned to both the top and bottom of the parent, and its height changes as the parent's height changes
- Common
Center: Based on the center of the parentScale: Keeps the same ratio as the parent's size
Child elements of a frame have Left and Top constraints by default, so even when you resize the frame, every child element always stays positioned from the top left.
If you change the constraints of the third child element of the frame to Right and Bottom, you can see that its position changes when the frame is resized.
If you change the constraint of the second child element in the middle of the frame to Center, it always stays in the center, even when the frame is resized.
And if you change the constraint of the first child element of the frame to Scale, you can see that it scales up or down at the same ratio as the frame's size.
# Components
A Component is a reusable UI element, and it is basically divided into a Main Component and Instances.
It is easy to think of the main component as the original and an instance as a copy.
When you edit the main component, the change is reflected in every instance, and you can also apply individual changes to each instance.
Let's turn a simple button into a component to understand main components and instances.
Right-click the simple button layer created as follows and choose Create component.
The icon and color of the button layer then change, and it becomes a main component.
A main component is marked with the ❖ icon.
To use the component you created, you need to insert it from the Assets menu.
You can insert an instance by following the steps in the next image.
In step 3, drag the component you want onto the canvas, or click the Insert instance button in step 4.
A new button instance is then added, and to tell them apart, the main component is marked with the ❖ icon, and the instance is marked with the ◇ icon.
Now you can reuse many instances based on the main component.
And if you change the button's color or text in the main component, the change is reflected in every instance in the same way.
| Concept | Web | Android |
|---|---|---|
| Main Component | Component definition (.vue, .tsx) |
@Composable function / XML layout |
| Instance | Component usage (<Button />) |
Button() call / <include> |
| Override | Passing props (<Button text="OK" />) |
Passing parameters |
# Variants
With Variants, you can create the different variations that a single component can have.
Let's offer several button styles with variants.
Right-click the main component layer and choose Main component > Add variant.
If you repeat this step once more, three variant layers (Default, Variant2, Variant3) are created for the main component, and each variant is marked with the ◆ icon.
On the canvas, you can see a dashed component area around the variants, along with the component name.
Then edit each variant layer into the style you want.
Here, I made button styles to use for OK, Cancel, and Delete.
You can also create a new variant faster and more easily by selecting a variant and clicking the + at the bottom, or by using the Ctrl(Cmd) + D shortcut.
Names like Default and Variant2 are not intuitive, so let's rename the variants.
First, select the Default variant layer.
Then, in the right sidebar, click the value of 'Property 1' and choose the Rename... menu at the bottom.
Enter Primary as the new value.
In the same way, select each variant layer and rename Variant2 to Secondary and Variant3 to Danger.
Now you can choose among several styles in a button instance.
If you select the button instance you inserted earlier and change the value of Property 1 in the right sidebar, you can see the style change to match the value.
The name Property 1 is not intuitive, so let's change it to something else.
Select the main component and choose Edit property for Property 1 in the right sidebar.
Then change the name from Property 1 to Variant.
(You can use any other name you like.)
If you select the button instance again, you can see that the name has changed as follows.
# Text
Changing the button label in one variant of a component does not change the labels of the other buttons.
If you want to manage the button labels all at once, you can use the component's Text property.
First, select the main component.
Click Create property in the right sidebar and choose Text from the menu that appears.
Set the text property's Name to Label and its Value to Button, then click Create property.
A new text property is created, but a warning shows that it is not used yet.
Select all the text layers of the button that you want to connect to the text property.
Once you have selected all the text layers, click the Apply variable/property button in the right sidebar.
Then choose the Label text property you created above from the menu that appears.
Now the text in every variant layer is unified, and editing it changes all of the text.
In an instance, you can change the value in the Label property of the right sidebar.
# Boolean
With a Boolean property, you can control whether a specific layer of a component is hidden or shown.
Let's use this feature to set whether the button uses an icon.
First, select the main component, click Create property in the right sidebar, and choose Boolean from the menu.
Set the property's Name to Has Icon and its Value to True, then click Create property.
Let's start with the Primary variant layer.
Add text as the first child of the variant and type the characters check.
Then, in the right sidebar, change the Typography of this text to Material Icons.
You can see that the characters check have turned into an icon on the canvas.
Copy the icon layer to the other variants as well and change its color to match.
Now select the icon layers of every variant to apply the boolean property.
In Appearance in the right sidebar, click Apply variable/property and choose the Has Icon property you created above.
Now the icon layer is shown or hidden depending on the True or False value of this property.
The icon will not be used by default, only when needed, so click Toggle layer visibility on every icon layer to hide them on the canvas for now.
In an instance, you can switch between True and False with a toggle in the Has Icon property of the right sidebar.
# Separating and detaching
Select the variant layer you want and drag it outside the component area (the dashed line).
It then becomes a new, independent component instead of a variant of the existing component.
When you no longer use a component or want to rebuild it, there is no feature to dissolve it directly, but you can work around this with an instance.
Right-click an instance layer of the component and choose Detach instance.
The instance loses its link to the main component and becomes a regular layer, and you can delete the original component if needed.
# Variables
Variables act as Design Tokens.
When you define one variable, it can have different values for different modes, such as dark mode and light mode.
Variables are organized hierarchically in the order of collection, group, and variable.
You can check variable information in the right sidebar, as follows.
- Collection: The top-level category, which divides variables by purpose or domain
- Group: Divides variables further within a collection
- Nested subgroup: A subgroup nested in a group that divides variables even further
- Variable: The unit that holds the actual value, which can have a different value for each mode
12345678910Collection ├─ Group │ ├─ Variable │ ├─ Variable │ └─ Subgroup (can be nested) │ ├─ Variable │ └─ Variable └─ Group ├─ Variable └─ Variable
# Creating variables
With no layer selected, go to the right sidebar > Variables > Open variables.
At first there are no variables, so click the Create button and choose the type of variable you want, such as Color, from the menu that appears.
The variable is created with a default name and value, so just change the name and value.
If you use the / symbol in the name, you can create a variable and a group at the same time.
You can also create a variable directly from a color or other value in an existing design.
Select an element, choose the color it uses in the right sidebar as in the next image, and turn that color into a variable right away.
In the same way, turn the colors used by the remaining Secondary and Danger variants of the button component into variables.
If you click Open variables in the right sidebar again, you can see the variable list, as in the next image.
Also rename the collection to Variables.
Now you can reuse the variables elsewhere.
When you set a value such as a color or text, you can choose a variable from Libraries.
# Modes
All the buttons we have made so far were Dark Mode versions.
To use the buttons in Light Mode as well, let's use the Mode feature of variables.
First, design a new button in a light mode version.
If you click the Add new mode button, the Value column splits into Mode 1 and Mode 2.
Then edit each variable value in Mode 2 to match the new light mode button design.
To make each mode clear, rename Mode 1 and Mode 2 to Dark Mode and Light Mode.
Now that the modes are ready to apply, let's actually show the buttons in light mode.
Wrap the area to show in light mode in a frame, and lay out new button instances for each variant.
Select the frame that wraps the buttons and choose Apply variable mode in Appearance in the right sidebar.Dark Mode is selected automatically for the Variables collection, so change it explicitly to Light Mode.
The frame itself then switches to Light Mode, and you can see every button inside it displayed to match.
# Export and import
You can export a variable collection as JSON files, or import variable files exported from another design.
If you right-click a collection in the variables panel as follows, you can choose the Export modes feature.
A zip file named after the collection, such as Variables.zip, is then downloaded.
When you unzip it, you can see the variable files (JSON) separated by mode, as follows.
123Variables/ ├─ Dark_Mode.tokens.json └─ Light_Mode.tokens.json
You can import these JSON files into another design and use them as variables.
Right-click a collection in the variables panel, choose Import, and select the exported variable files.
Rename the default name Collection 1 to whatever you like and use it.
# Prototyping
Prototyping is a feature that simulates transitions and interactions between screens.
You can build a prototype that behaves like a real app or website to validate the design.
Select the Prototype tab in the right sidebar to switch to prototyping mode.
To set the start screen of the prototype, select a top-level section or frame and add a Flow starting point in the Prototype tab.
When you select an element such as a frame, a small round handle appears on its right.
Drag this handle to the target screen or another frame to connect them, and an interaction is created.
# Interactions
An interaction is made up of a Trigger and an Action, and you can set an Animation for screen transitions.
A Trigger sets the condition that runs the interaction.
None: No triggerOn click / On tap: When the element is clicked or tappedOn drag: When the element is draggedWhile hovering: While the mouse is over the elementWhile pressing: While the element is being pressedKeyboard / Gamepad: When a specific keyboard key or gamepad button is pressedMouse enter: When the mouse enters the element areaMouse leave: When the mouse leaves the element areaMouse down: When a mouse press or touch beginsMouse up: When a mouse press or touch is releasedAfter delay: After a set amount of time has passed
An Action sets what happens when the trigger fires.
None: No actionNavigate to: Switch to another frameChange to: Change the component's variantBack: Go back to the previous screenScroll to: Scroll to a specific position on the same screenOpen link: Open an external URLSet variable: Change a variable valueSet variable mode: Change a variable's modeConditional: Run different actions depending on a conditionOpen overlay: Show a modal or popupSwap overlay: Replace the current overlay with another overlayClose overlay: Close the open overlay
An Animation sets the effect to apply during a screen transition.
Instant: Changes immediately with no transition effectDissolve: Transitions with a fade in/outSmart animate: Automatically connects layers with the same name for a smooth transitionMove in: The new screen slides in from one directionMove out: The current screen slides out in one directionPush: The new screen appears while pushing the previous screen outSlide in: The new screen slides in over the existing screenSlide out: The current screen slides out
# Scrolling and fixed position
When content goes beyond the frame area, you can set how it scrolls in the prototype.
This lets users scroll through content larger than the frame, such as long lists, body text, or galleries.
Select the frame area and set Overflow under Scroll behavior in the Prototype tab.
None: No scrollingVertical: Vertical scrollingHorizontal: Horizontal scrollingBoth: Both horizontal and vertical scrolling
In a prototype, you can also fix specific elements on the screen regardless of scrolling.
Use this for elements that should always be visible on the screen, such as navigation bars, headers, and floating buttons.
Select the element to fix and set Position under Scroll behavior in the Prototype tab.
# Viewing prototypes
To run a prototype, click the Prototype view button at the top right.Present runs the prototype full screen in a new tab, and Preview opens it in a small window next to the editor so you can check your edits right away.
If you install the Figma app, you can use its mirroring feature to check the prototype on a real mobile device.
The following images were taken on an actual Galaxy Fold.
# Design handoff
Design handoff is the process of passing a finished design to developers so they can build it into a real, working product.
When the design is done, click Share at the top of the right sidebar to share it with planners, developers, and others.
The Share to selection "content" panel then appears as follows, and you can click Copy link at the top right to copy a link and share it.
If you open a shared link without signing in, you can view the design or prototype, but features such as comments, inspection, and editing are not available.
The toolbar at the bottom prompts you to sign up and sign in, as follows.
Unless the developer uses the designer's account, the developer needs to sign up, sign in, and then open the link.
Once signed in, the developer gets the basic features needed for development, such as comments and inspection, and can ask the designer (owner) for permission to use extra features such as direct editing or Dev Mode.
With the basic features and no extra permissions, when you select an element on the canvas, you can check information such as the layout and colors applied to it in the Properties tab of the right sidebar.
If you click the Copy button at the top right of a section such as Component properties or Layout, you can copy CSS code like the following.
The copied code includes basic style information, but it needs editing before you actually use it, for example because some values have no units or some properties are meaningless.
12345678width: 372; height: 74; border-radius: 16px; border-width: 1px; padding: 16px; gap: 12px; angle: 0 deg; opacity: 1;
To check the distance between two elements, select the reference element and hover over the other element while holding the Alt(Option) key, and the exact distance is shown with red lines.
You can also extract assets used in the design, such as icons and images.
To support devices with different resolutions, you can add several sizes or formats and export them.
Select the asset element to extract and click the Add export settings button in Export in the right sidebar.
Click the button several times to add the sizes and formats you want.
# Comment tools
# Comments
You can add comments directly in Figma to ask questions or exchange feedback about specific elements.
You can write comments both in the design and in Dev Mode.
Choose Comment in the toolbar at the bottom of the screen.
You can add a comment by clicking anywhere you like.
Organize your questions or opinions about the design so the other person can understand them well, and then submit.
When a comment is added, other people can check for new unread comments on the canvas, in the toolbar, and in the right sidebar.
New unread comments are shown in blue or green.
You can communicate by leaving more comments.
In a comment, choose Thread actions to mark the comment as unread, copy a link to the comment to share it, or delete the comment (thread).
Or click the Mark as resolved button to close out the question or opinion in that comment.
Once a comment is marked as resolved, it no longer appears in the Comments area of the right sidebar.
To see resolved comments, filter by Show resolved comments in Comments in the right sidebar.
# Annotations
Annotations are a feature that lets designers record implementation details for developers directly on top of the design.
For specific elements on the canvas, you can freely leave notes as text or properties, such as how they are aligned, how they resize, and the context needed to understand them when moving them into code.
Choose Annotation in the toolbar.
Use the annotation tool to select the element you want on the canvas, and write an annotation by adding text, a category, properties, and more.
When there are many annotations, you can hide or show them again with View > Annotation in the menu.
To write effective annotations, set up and follow rules like these.
- Annotations are much easier to read if you use only one or two types.
- For identical repeated elements, add an annotation only to the first one and ignore the rest or mark them as the same.
- If you categorize annotations by type, such as development issues, accessibility, and responsiveness, developers can find the information they need more quickly.
# Measurements
With the measurement feature, you can visually show distances and sizes on the canvas.
While annotations convey context and property information, measurements visualize the distance between two elements or their size as exact numbers.
Choose Measurement in the toolbar.
When you hover over an element on the canvas, the measurement starting point is shown with a red line.
Drag from the starting point to the end point you want, and the value is visualized.
You can move the visualized value to any position you like.
# Dev Mode
Dev Mode is a paid Figma feature and a mode specialized for developers.
You need the Professional Dev Seat or a higher plan to use this mode.
Dev Mode is a mode for developers to 'read the design'.
It supports features needed for development that the regular mode does not, such as specs, code snippets, and asset extraction.
| Feature | Regular mode | Dev Mode |
|---|---|---|
| Checking specs | Simple properties panel | Developer-friendly inspect panel |
| Code generation | CSS only | CSS, Android, iOS, and more |
| Measuring distance | One at a time with the Alt(Option) key |
Details shown automatically |
| Extracting assets | Export one by one | One-click export |
| Comparing changes | - | Compare changes |
| Status management | - | Ready for dev workflow |
# Code snippets
One of the handy features of Dev Mode is that it generates code snippets automatically.
When you select an element, you can check and copy code in the language you use right in the right sidebar.
The supported languages are as follows.
- CSS
- Android: XML, Compose
- iOS: SwiftUI, UIKit
# Extracting assets
In Dev Mode, you can easily extract assets used in the design, such as icons and images.
If you select a parent frame, you can see and download all the assets used inside it at once.
With Image download settings, you can also add several sizes or formats for all assets or for individual assets.
Export assets according to their purpose, as follows.
| Purpose | Format | Type | Notes |
|---|---|---|---|
| Simple, general assets | SVG | Vector | Resolution-independent, some styling possible |
| Complex, photo-like assets | JPG, PNG, etc. | Bitmap | Highly compatible |
When you use bitmap images such as JPG or PNG, you need to export them at several scales (1x, 2x, and so on) to support high-resolution displays.
If you add scales in Figma's export settings and then export, suffixes such as @2x and @3x are added to the file names automatically.
In HTML, the srcset attribute lets the browser automatically pick the image that matches the display density.
123456<img src="my-image.png" srcset="my-image@2x.png 2x, my-image@3x.png 3x" alt="Product image" width="320" height="200" />
Or you can use the <picture> element to also provide alternative images (fallbacks) such as WebP.
1234567891011<picture> <source srcset="my-image.webp, my-image@2x.webp 2x, my-image@3x.webp 3x" type="my-image/webp" /> <img src="my-image.png" srcset="my-image@2x.png 2x, my-image@3x.png 3x" alt="Product image" width="320" height="200" /> </picture>
In Android Compose, you place images in density qualifier folders so the system automatically picks the image that matches the device density.
| Density qualifier | Scale |
|---|---|
drawable-mdpi |
1x |
drawable-hdpi |
1.5x |
drawable-xhdpi |
2x |
drawable-xxhdpi |
3x |
drawable-xxxhdpi |
4x |
SVG assets do not need density selection, so convert them to Vector Drawables (.xml) with the Vector Asset feature in Android Studio and place them only in the drawable/ folder, without a density qualifier.
123456789res/ ├── drawable/ │ └── icon.xml ├── drawable-mdpi/ │ └── my-image.webp ├── drawable-xhdpi/ │ └── my-image.webp └── drawable-xxhdpi/ └── my-image.webp
When you reference images placed this way with painterResource in Compose, the system automatically picks the image that matches the device density.
12345Image( painter = painterResource(id = R.drawable.my-image), contentDescription = "My image", modifier = Modifier.size(320.dp, 200.dp) )
# Design tokens
Design tokens define design properties such as colors, typography, spacing, and corner radius as name-value pairs, and as explained earlier, variables play that role in Figma.
With tokens, the values in the design and the code always match, you only need to change one place when you change the theme or support dark mode, and designers and developers can communicate using the same names.
With nothing selected on the canvas, open the variables panel with Open variables table in the right sidebar and choose the Export modes feature on the collection.
As we saw earlier, a zip file named after the collection is then downloaded.
When you unzip it, you can see the variable files (JSON) separated by mode, as follows.
123Variables/ ├─ Dark_Mode.tokens.json └─ Light_Mode.tokens.json
As in the following example, the JSON file shows details, including the values ($value) of the variables grouped into each group (Fills, Labels).
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293{ "Fills": { "Primary": { "$type": "color", "$value": { "colorSpace": "srgb", "components": [0.05098039284348488, 0.4313725531101227, 0.9921568632125854], "alpha": 1, "hex": "#0D6EFD" }, "$extensions": { "com.figma.variableId": "VariableID:2051:4", "com.figma.scopes": ["ALL_SCOPES"], "com.figma.isOverride": true } }, "Secondary": { "$type": "color", "$value": { "colorSpace": "srgb", "components": [0.11764705926179886, 0.16078431904315948, 0.23137255012989044], "alpha": 1, "hex": "#1E293B" }, "$extensions": { "com.figma.variableId": "VariableID:2051:6", "com.figma.scopes": ["ALL_SCOPES"], "com.figma.isOverride": true } }, "Danger": { "$type": "color", "$value": { "colorSpace": "srgb", "components": [0.20392157137393951, 0.09803921729326248, 0.1411764770746231], "alpha": 1, "hex": "#341924" }, "$extensions": { "com.figma.variableId": "VariableID:2051:8", "com.figma.scopes": ["ALL_SCOPES"], "com.figma.isOverride": true } } }, "Labels": { "Primary": { "$type": "color", "$value": { "colorSpace": "srgb", "components": [1, 1, 1], "alpha": 1, "hex": "#FFFFFF" }, "$extensions": { "com.figma.variableId": "VariableID:2051:10", "com.figma.scopes": ["ALL_SCOPES"], "com.figma.isOverride": true } }, "Secondary": { "$type": "color", "$value": { "colorSpace": "srgb", "components": [0.6771448850631714, 0.736008882522583, 0.8323317170143127], "alpha": 1, "hex": "#ADBCD4" }, "$extensions": { "com.figma.variableId": "VariableID:2051:12", "com.figma.scopes": ["ALL_SCOPES"], "com.figma.isOverride": true } }, "Danger": { "$type": "color", "$value": { "colorSpace": "srgb", "components": [1, 0.2672025263309479, 0.2672025263309479], "alpha": 1, "hex": "#FF4444" }, "$extensions": { "com.figma.variableId": "VariableID:2051:14", "com.figma.scopes": ["ALL_SCOPES"], "com.figma.isOverride": true } } }, "$extensions": { "com.figma.modeName": "Dark Mode" } }
If you convert the exported JSON data into code for each platform, you can use it as follows.
In Android (Kotlin), define a color object for each light/dark mode and map each variable name to a property.
12345678910111213141516171819202122232425val LightAppColors = AppColors( surface = Color(0xFFFFFFFF), primary = Color(0xFF3C94FF), secondary = Color(0xFFE7F0F9), label = Color(0xFF1A1A1A), labelSub = Color(0xFF526682), labelOnPrimary = Color(0xFFFFFFFF), labelOnSecondary = Color(0xFF526682), danger = Color(0xFFFF4B4B), dangerBg = Color(0xFFF9D9E4), border = Color(0xFFD5E0EC) ) val DarkAppColors = AppColors( surface = Color(0xFF101822), primary = Color(0xFF0D6EFD), secondary = Color(0xFF1E293B), label = Color(0xFFFFFFFF), labelSub = Color(0xFFADBCD4), labelOnPrimary = Color(0xFFFFFFFF), labelOnSecondary = Color(0xFFADBCD4), danger = Color(0xFFFF4444), dangerBg = Color(0xFF341924), border = Color(0xFF2A3546) )
On the web (CSS), define them as CSS variables and override the dark mode values with the :root.dark selector.
12345678910111213141516171819202122232425:root { --surface: #ffffff; --primary: #3c94ff; --secondary: #e7f0f9; --label: #1a1a1a; --label-sub: #526682; --label-on-primary: #ffffff; --label-on-secondary: #526682; --danger: #ff4b4b; --danger-bg: #f9d9e4; --border: #d5e0ec; } :root.dark { color-scheme: dark; --surface: #101822; --primary: #0d6efd; --secondary: #1e293b; --danger-bg: #341924; --label: #ffffff; --label-sub: #adbcd4; --label-on-secondary: #adbcd4; --danger: #ff4444; --border: #2a3546; }
# Automating tokens
Converting variables into design tokens and saving them by hand is very tedious.
Let's automate this easily with the GitFig plugin for Figma.
GitFig is a tool that syncs design tokens from Figma to a Git repository.
Designers can change design tokens in Figma and commit/push them directly to a branch of a specified repository.
In the Figma toolbar, choose Actions and search for GitFig in Plugins & widgets.
In Run for the GitFig plugin, click the Open Sync Panel button.
The plugin is then installed.
When the plugin runs, you need to sign in to connect it to GitHub.
Click the Sign in with GitHub button to start signing in.
To connect GitFig, copy the authentication code and click the Open GitHub button.
When the browser opens, click the Continue button with the account you want to connect.
Paste the authentication code you copied earlier and click the Continue button.
Next, in the permissions and authorization step, click the Authorize ds1 button to give final approval.
Back in Figma, the GitFig plugin shows that the connection is complete.
Click the Connect Repository button right away.
Enter the name of the repository you want in your GitHub account.
After a short search, you can see the list of branches in that repository.
Choose the branch you want to connect and click the Connect button below.
You can then see the folder and file structure of that branch.
Choose the JSON file you prepared in advance for storing the Figma design tokens.
Then choose the type and format to save, and click Save.
The available formats are as follows.
- Auto-detect: Analyzes the file content to detect the format automatically
- W3C Design Tokens: The standard format of the W3C Design Tokens Community Group
- Style Dictionary: The format used by Amazon's Style Dictionary tool
- Tokens Studio: A format compatible with the Tokens Studio (formerly Figma Tokens) plugin
- Custom JSON: Export with a user-defined JSON structure
Now you need to commit and push these changes.
First, choose Stage All in the Changes section to stage the changes.
Write a commit message for the changes and click the Create Commit button to commit.
Finally, click the Push button at the bottom to push to the remote repository.
Or you can click the Create Pull Request button at the bottom to create a PR, review it, and then merge it.
# Ready for Dev
When designers finish their work, they can mark sections, frames, components, and more with the Ready for dev status.
This shows that the design work is done and implementation (development) can begin.
Developers only need to filter by the Ready for dev status in Dev Mode and implement what they find.
This prevents the mistake of implementing designs that are still in progress.
Also, the Ready for dev status highlights when it was most recently updated, so you can easily tell whether anything has changed after the initial implementation.
When the implementation is done, developers can mark it with the Completed status in Dev Mode.
This lets both designers and developers see at a glance which screens have been implemented and clearly manage the remaining work.
However, to use the Completed status, you need the Organization plan or higher.
# Comparing changes
With the Compare Changes feature in Dev Mode, you can visually compare changes in a design.
Select the section or frame you want to compare and click the 'Compare to previous version' button in the right sidebar.
The version comparison panel then appears as follows.
You can use features such as the version history, edited layers, assets from the current and previous versions, and code comparison.
Changes are shown with the following highlight colors.
- Added: A new element that was not in the previous version was added
- Changed: Properties such as the size or color of an existing element were modified
- Removed: An element that was in the previous version was deleted
# Using MCP
MCP (Model Context Protocol) is a protocol that lets AI tools connect to external services.
If you connect the Figma MCP server to an AI coding tool such as VS Code, Cursor, or Claude Code, the AI can read Figma designs and generate code.
| Feature | Description |
|---|---|
| Getting design context | Passes the layout, styles, and properties of the selected node to the AI |
| Generating screenshots | The AI visually analyzes a screenshot of a specific frame |
| Getting variables | Converts design token (variable) definitions into code |
| Generating code | Automatically generates UI code based on the design context |
If you use Figma in a web browser, click the Connect to AI agent button under MCP in the right sidebar while nothing is selected on the canvas.
From the VS Code, Cursor, Claude Code, and Other editors items on the left of the panel, choose the AI coding tool you want and set up the connection by following the instructions.
Let's use Figma MCP with VS Code Copilot.
Click the + Add button in the VS Code item under MCP client settings.
Install Figma MCP in VS Code.
Go through the external authentication process as shown in the images below.
Let's use Figma MCP with GitHub Copilot Chat.
Search for GitHub Copilot Chat in the VS Code extensions and install it.
Search for and run Chat: Open Chat in the Command Palette, or press the Ctrl(Cmd) + Alt(Option) + B shortcut, and the Copilot chat panel appears.
If you run the #get_design_context hash command in the chat, you can check whether Figma MCP is connected properly.
To use GitHub Copilot Chat, you need to sign in.
If the connection works, go back to Figma.
Select the element you want in the design, such as a section, frame, or component, and look at the MCP item in the right sidebar: you can see the estimated token count for the AI to implement that element and a Copy example prompt button.
Click the Copy example prompt button to copy a simple prompt, Implement this design from Figma., along with the Figma URL of the selected element.
Go back to the VS Code Copilot chat and enter the copied prompt.
The URL in the prompt is a reference to the element selected in Figma, so you must not change it.
Apart from the URL, you can change the prompt however you like.
Once the processing finishes, you can see the related content implemented in your project.
If you use the Figma desktop app, unlike in the web browser, you see an Enable desktop MCP server button in the right sidebar.
Click the Enable desktop MCP server button.
The local server should be enabled as follows.
The URL of the Figma MCP local server then appears right above the toolbar.
Click the Copy URL button.
In VS Code, proceed as follows.
Search for and run 'MCP: Add Server' in the Command Palette (Ctrl(Cmd) + Shift + P).
First, choose the HTTP (HTTP or Server-Sent Events) server type.
Paste the Figma MCP local server URL you copied above.
Set the name of the MCP server.
We recommend figma-desktop so it is easy to find later.
Choose whether to register the Figma MCP local server for the current project only or for all local projects.
This time, let's use Figma MCP through Claude Code as well.
Add the Figma MCP local server URL you copied above to the end of the claude mcp command as follows, and run it in the terminal.
If the URL has not changed, you can copy and use the following command as it is.
1claude mcp add --transport http figma-desktop http://127.0.0.1:3845/mcp
As we saw in VS Code, run Claude Code, enter the example prompt you copied from Figma, and wait for the implementation.
# Working with designers
# Collaboration workflow
For effective collaboration, what matters is the order and the agreements under which designers and developers work together.
Let's look at a collaboration workflow centered on Dev Mode.
The following steps may not end in a single pass.
Problems found in QA lead to design changes, and development and QA repeat, forming a cycle.
Both sides need to communicate while checking the same screens and the same tokens to keep misunderstandings from piling up and to reduce rework.
1. Kickoff:
When a project starts, it is a good idea for designers and developers to get together and agree on a few common rules.
Typical things worth agreeing on in advance are as follows.
- Defining the design system: Decide together on design tokens such as colors, typography, and spacing, and on the scope of shared components.
- Naming rules: Agree on naming rules in advance so that Figma layer names can become variable or class names in the code.
- Variable structure: If you agree on how to organize the collections and modes of Figma variables so they map directly to the theme system in the code, later work goes much more smoothly.
2. Design:
Based on the rules set at the kickoff, the designer moves on to designing the screens in earnest.
It is important for the designer not just to make good-looking screens, but to structure them so developers can interpret them easily.
- Using variables: If you turn values such as colors and spacing into variables and connect them instead of typing them in directly, developers can check the design tokens right away in Dev Mode.
- Component-based design: If you manage repeated UI elements as Figma components, developers can see the component's variants and other properties at a glance in Dev Mode, and they naturally turn into reusable components during development.
Ready for devstatus: If you mark finished sections with theReady for devstatus, developers can tell them apart from parts still being designed in Dev Mode and develop accordingly.
3. Development:
Once sections marked Ready for dev appear, developers open Dev Mode and start implementing.
- Checking
Ready for devsections: Filter by theReady for devstatus in Dev Mode to pick only the sections ready to implement and make the scope of work clear. - Checking specs and referring to code snippets: Check the size, color, spacing, and typography information shown when you select an element, and refer to code snippets to implement quickly.
- Token-based implementation: If you move the design tokens set by the designer into variables in the code and use variable references such as
var(--color-primary)instead of hardcoded values (#3B82F6), maintenance is much easier even when the design changes later. - Communicating through Figma comments: If something is confusing or missing during implementation, adding a comment directly on that element in Figma lets you ask questions and get answers right within the design context, without separate communication.
4. QA:
When the implementation is done, designers and developers review the result together.
- Comparing changes: Put the original design and the actual implementation side by side and check for visual differences.
- Checking and fixing specs: Find and fix things like a gap that should be
8pxbut was implemented as10px, or a color token that was mapped incorrectly. - Final approval: The designer checks the implementation and, if everything is fine, marks the work on that section as complete.
# What to ask designers in advance
To translate the designer's intended design into code accurately, it is important to share in advance what information you need during development.
If you work out the following points together, both sides can work much more efficiently.
- Using auto layout: If frames use auto layout, Dev Mode automatically shows direction, gap, padding, and alignment information, so developers can implement the layout accurately.
- Using variables: If colors, spacing, corner radius, and more are connected to variables, Dev Mode shows the token names, so developers can easily map them to design tokens instead of hardcoding values.
- Meaningful layer names: Names that show the role, such as
headerandcard-title, help developers quickly understand the design structure and use them right away as variable or component names in the code. - Ready for dev status: If sections or frames ready for development are marked with the 'Ready for dev' status, developers can clearly see which screens to work on first.
- Variant setup: Components such as buttons and inputs need variants for each state, such as default, hover, and disabled, so developers can check and implement every state without missing any.
- Export settings for assets: If export formats (SVG, PNG, etc.) and scales are set up in advance for icons and images, developers can download assets with a single click in Dev Mode.
- Consistent multiples for sizes, spacing, and more: If the values used for sizes, margins, and gaps are unified to consistent multiples such as 4, 8, and 12, tokenizing becomes easier and you can keep a consistent design system in both the design and the code.
# QA checklist
When the implementation is done, compare the design and the implementation item by item.
Check the following basic items and add the items your project needs.
- Compare whether the outer/inner spacing in the design matches the implementation
- Compare whether element sizing such as hug and fill behaves the same way in the code
- Compare whether the gap set in auto layout matches the alignment gap in the code
- Compare whether the variable names used for backgrounds, text, and borders map correctly to the variable names in the code
- For elements with transparency, compare whether the code distinguishes between the element's opacity and the color's own transparency
- Compare whether the font, size, weight, line height, and letter spacing of the text styles match the text styles in the code (note that they may differ depending on the output environment)
- Compare whether text alignment, line limits, and ellipsis handling are implemented as the design intends
- Compare whether the corner radius values match the corner rounding in the code (check each corner separately if they have different values)
- Compare whether the direction, blur, spread, and color of shadow effects match the shadow values in the code
- Check that every variant and state, such as hover and disabled, of interactive elements like buttons, inputs, and checkboxes is implemented in the code without exception
- When focus indicators are defined in the design, compare whether focus styles are also defined in the code
- If the design includes screens for states such as loading, empty, and error, check that every corresponding conditional branch is implemented in the code
- Compare whether the wrap setting in auto layout matches how child elements wrap in the code
- Compare whether the constraint settings match how the implementation responds when the actual screen size changes
- Compare whether the breakpoints defined in the design for responsive layouts and the resulting layout changes match the implementation
- Compare whether the size, color, and surrounding spacing of icons match the implementation
- Compare whether the image fill mode matches how images are displayed in the code (Cover, Contain, etc.)
- Compare whether the light/dark mode values of variables map correctly to the theme variables in the code
- When switching between light and dark mode, check that every token, including not only backgrounds and text but also shadows, borders, and icon colors, switches to match the mode values
Thanks for reading to the end.
Likes and kind comments help keep this blog going!