DEV Community

tdesero
tdesero

Posted on

My attempt at programming a design to code translator in Figma

I created a plugin for Figma (AutoHTML) that converts designs into code like HTML, Vue or React with classic CSS styling or Tailwind CSS. It can be used by developers as a starting point. In this article I want to give you some background about how it went.



Example of converted frame: The preview in the plugin’s window is already HTML/CSS displayed in an iframe.


In the beginning of the year I switched to a new company and finally had to learn Figma (a bit late to the party I guess). Obviously Figma has a quite low entry barrier and it is just made to be learned fast. So I felt comfortable with the application within a few days and – as a designer who likes to code – I was really impressed how you can easily create complex and partly responsive layouts in a few clicks with Auto Layout. In the end it even felt redundant that someone had to manually rewrite all the CSS again I just defined in the Figma UI. So I decided, maybe it makes sense to go one step further and look at the Figma Plugin API to get all the frame data and convert it to some simple divs with some Flexbox CSS added.

First steps

So I started by having a look at the Figma Plugin API documentation. Setting up the plugin was quite straight forward: There was an item for that in the Figma Desktop App’s main menu. You just had to click a few times and you were ready to go with a very basic setup of your plugin. That was easy.

In the Figma Plugin API everything is presented in nodes meaning that everything you look at in the designs is just a big JavaScript object. Once I had a look at all the properties of the object I quickly realised that there really is almost all the file information available. Alignment, padding, gaps, fills, strokes… – just everything. After a few hours of work I was able to translate at least the Auto Layout information into HTML with some additional CSS. Nice!

Make it look better

I was really impressed how far I got already in a few hours. But as a designer I was also a bit dissatisfied about the fact that the output preview was looking so ugly. Ok, so I added a bit of style to it. A bit of background color here, some border radius there and some basic text styling. This quickly became a quite entertaining challenge. So every once in a while I wasted an hour or two to get a bit of a nicer result. After a few weeks the result was already looking quite similar to the actual design and I somehow managed to keep the CSS class names more or less the same as the original layer names in Figma. This was something that a lot of other design-to-code plugins were missing (at that time) and I think generative class names are not really well readable for humans.

Improve the UI

Until that point the plugin was just a little window with some very very basic bootstrap tabs that could only be launched after selecting a frame and wasn’t updating anything if you selected a new frame. That means if you changed your selection you had to rerun the plugin. It was ok but I was seeing other plugins that updated the UI after the selection in Figma changed and that felt a lot more like for example Chrome developer tools. So I decided to go for something similar and also rewrite the UI in React and make it look a bit more Figma native.

Make it even more useful

So now I had a nice UI and an already quite cool HTML converter. But it turned out that in real life projects this still wouldn’t be enough. For example you don’t want to hardcode all the color values or fonts if you already worked with styles (variables) in Figma. And even if the aim of the plugin is not to create production ready code it is just annoying to always switch from code editor to Figma to get all the colors one by one. It turned out that you can also get the Figma Styles that are attached to node. So I added them to the output with a fallback value if you don’t want to use it.

/* Example CSS output */

.button,
.button * {
  box-sizing: border-box;
}
.button {
  background: var(--primary, #222aed);
  border-radius: 8px;
  padding: 12px 24px 12px 24px;
  display: flex;
  flex-direction: column;
  gap: 46px;
  align-items: center;
  justify-content: center;
  position: relative;
}
.button__btn-text {
  color: var(--white, #ffffff);
  text-align: center;
  font: var(--button-text, 700 14px "Space Grotesk", sans-serif);
  position: relative;
}
Enter fullscreen mode Exit fullscreen mode

In real projects you also would likely work with Frameworks like React or Vue and not just regular HTML with CSS. So to face that challenge I first had to rearrange the code a bit as it was overly messy at that time (I don’t feel bad about that, I was doing all that in my free time😁). After doing that I found some ways to add Support to convert it to major web frontend frameworks like React, Vue and Tailwind. At about the same time, Figma launched some additional component properties like boolean, text and component swaps and I tried at least to have some basic support for the first two as these are just awesome features. To be honest it does not work perfectly all the time but it feels like magic if you create a text property on a component in Figma, convert it to a React component and you are then able to change the text of the component by passing some props.



If you select a component directly you will have working text & boolean properties in the React output.


What was still bad at that time is that everything was converted into a single file even if the designer worked with nicely created components in Figma. This can result in super complex and long markup that is very difficult to read. The solution obviously was to convert it into multiple component files but that did not turn out to be easy. I had to accept some tradeoffs as components with variants are still just handled a bit differntly in Figma than in code. Actually variants of components in Figma are basically just components itself, that can have a completely different structure for each variant of the same component set. So I needed to treat them as different components when converting instances inside the current selection. Otherwise the result may look completely different. This is not perfect but still better than thousand of divs.



The Plugin’s Setting Tab


I am still working on the plugin every now and then. If you want to try it, feel free: AutoHTML

Top comments (0)