How to create reusable HTML snippets for Ghost.io using Figma Dev Mode

Figma just launched a number of new features, including variables, better prototyping and an all new dev mode that helps designers translate their work into code much faster.
We have been wanting to create reusable marketing snippets for our Ghost.io blog for a while and decided to finally make it happen, using the Figma Dev Mode.

In this article, I will go over how I created our snippet design in Figma, translated it over to HTML and CSS and implemented it into our Ghost.io blog.

Let's jump right into it!

Setting up the Design

For this first iteration, my goal was to design a simple marketing component that fits the Codesphere CI and can be implemented into any Blog article.

I started out creating the design in Figma. This was pretty straight forward and standard. To make sure the design would be responsive, I utilized Figmas Auto Layouts for all frame elements which would turn into divs when implementing the design in HTML. I also made sure to use as few height and width properties as possible to have the elements scale according to the space available to them.

I then created a second frame and adapted the design for mobile screens, essentially only changing the Auto Layout direction of the main container from horizontal to vertical.

Implementing the design in HTML

To implement the design into HTML, I was finally able to make use of the new Dev Mode which shows the CSS properties of each element. This makes it possible to just copy and paste the values, streamlining the process of layouting and styling your HTML elements.
Unfortunately, Dev Mode doesn't export the HTML structure yet, so wou will have to write that by yourself, utilizing the values provided by Figma to create your stylesheet.

From my perspective, the new Dev Mode is great to get your designs off the ground and getting close to your desired output. Finalizing the components however, will require you to write some CSS and HTML yourself.
This means you definitely should know your way around HTML and CSS to finish up your designs!

Nonetheless, utilizing the property values provided by Figma, made it super fast to set up the element. You can take a look at it here.
This is the code I ended up with:

<style>
@import "https://rsms.me/inter/inter.css";

:root {
  font-family: 'Inter', sans-serif;
}

@supports (font-variation-settings: normal) {
  :root {
    font-family: 'Inter var', sans-serif;
  }
}

.info__container{display:flex;padding:40px;align-items:center;justify-content:center;position:relative;overflow:hidden;border-radius:19px;border:2px solid rgba(129,75,246,.4);background:linear-gradient(0deg,rgba(43,27,78,.4) 0%,rgba(43,27,78,.6) 100%),#080809}.content__wrap{display:flex;align-items:center;max-width:900px;flex-direction:row;gap:16px;justify-content:space-between}.blur-effect{width:728px;height:311px;position:absolute;left:-25px;bottom:-71px;fill:linear-gradient(140deg,rgba(175,44,187,.45) 0%,rgba(0,26,255,.45) 100%);opacity:.4000000059604645;filter:blur(52px)}.left__container{display:flex;position:relative;z-index:999;flex-basis:37%;flex-direction:column;justify-content:center;align-items:flex-start;gap:24px;align-self:stretch}.text__container{display:flex;flex-direction:column;align-items:flex-start;gap:16px;align-self:stretch}.text__heading{display:flex;flex-direction:column;align-self:stretch;margin:0;color:#FFF;font-family:Inter;font-size:32px;font-style:normal;font-weight:700;line-height:96.023%}.text__desc{display:flex;flex-direction:column;align-self:stretch;margin:0;color:#CCC;font-family:Inter;font-size:16px;font-style:normal;font-weight:400;line-height:normal}.btn{display:flex;padding:10px 40px;justify-content:center;align-items:center;gap:10px;border-radius:3px;background:#814BF6;color:#FFF!important;font-family:Inter;font-size:16px;font-style:normal;line-height:normal;text-decoration:none!important}.btn:hover{background-color:rgba(129,75,246,.75)}.right__container{display:flex;position:relative;z-index:999;flex-basis:63%;flex-direction:column;justify-content:flex-end;align-items:flex-start;gap:32px;align-self:stretch}.usp__container{display:flex;align-items:center;justify-content:start;gap:26px;align-self:stretch}.usp__icon{display:flex;padding:8px;justify-content:center;align-items:center;border-radius:5px;border:1px solid #814BF6}.usp__text span{color:#FFF;font-family:Inter;font-size:16px;font-style:normal;font-weight:700;line-height:normal}.usp__text p{color:#CCC;font-family:Inter;font-size:16px;font-style:normal;margin:0}.usp__svg{width:24px}.text__container p{padding:0 0 0 0!important;margin:0 0 0 0!important}@media screen and (max-width:600px){.content__wrap{flex-direction:column;gap:40px}}@media screen and (min-width:950px){.left__container{flex-basis:33%}}
</style>

<div class="info__container">
  <svg xmlns="http://www.w3.org/2000/svg" class="blur-effect" viewBox="0 0 693 218" fill="none">
    <path d="M-1.45455 174.421L-19.2727 12.2249L-25 -22L15.7273 -18.0319H131.545L211.727 6.27273L243.545 53.3939L368.273 62.8182L522.273 68.2743L703 150.612L624.727 289L216.818 140.196L-1.45455 174.421Z" fill="url(#paint0_linear_38_57)" fill-opacity="0.45"/>
  <defs>
    <filter id="filter0_f_38_57" x="-129" y="-126" width="936" height="519" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
      <feFlood flood-opacity="0" result="BackgroundImageFix"/>
      <feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
      <feGaussianBlur stdDeviation="52" result="effect1_foregroundBlur_38_57"/>
    </filter>
    <linearGradient id="paint0_linear_38_57" x1="103.545" y1="-9.59964" x2="469.427" y2="296.954" gradientUnits="userSpaceOnUse">
      <stop stop-color="#AF2CBB"/>
      <stop offset="1" stop-color="#001AFF"/>
    </linearGradient>
  </defs>
</svg>
   <div class="content__wrap">
  <div class="left__container">
      <div class="text__container">
        <p class="text__heading">Zero config cloud made for developers</p>
        <p class="text__desc">From GitHub to deployment in under 5 seconds.</p>
      </div>
      <a class="btn" href="https://example.com" class="https://signup.codesphere.com/?utm_source=blogSnippet&utm_campaign=blog">Sign Up!</a>
    </div>
    <div class="right__container">
      <div class="usp__container">
        <div class="usp__icon">
          <svg xmlns="http://www.w3.org/2000/svg" class="usp__svg" viewBox="0 0 15 16" fill="none">
    <path d="M4.03783 10.516C3.92061 10.3988 3.88276 10.2361 3.93283 10.0851C4.01973 9.8273 4.13563 9.49121 4.2747 9.10588L4.51642 8.43614H3.8044H0.704948C0.631302 8.43614 0.562855 8.3965 0.526438 8.33298C0.490608 8.27049 0.491168 8.19366 0.5283 8.13122L0.528559 8.13078L2.06649 5.53833C2.06652 5.53829 2.06654 5.53825 2.06656 5.53821C2.35762 5.048 2.88288 4.749 3.44992 4.749H5.86093H6.14402L6.28967 4.50625C6.354 4.39905 6.41919 4.29839 6.4868 4.19694C8.72808 0.89276 12.0526 0.771759 14.0874 1.14629L14.0888 1.14655C14.22 1.17031 14.3272 1.27405 14.3543 1.41447C14.7286 3.45236 14.604 6.77378 11.3016 9.01454L11.2995 9.01592C11.2076 9.07896 11.1053 9.14372 10.994 9.21046L10.7513 9.35611V9.63921V12.0502C10.7513 12.6183 10.4514 13.1452 9.96338 13.4327L9.96205 13.4335L7.36941 14.9714L7.36898 14.9717C7.30652 15.0088 7.22968 15.0094 7.16718 14.9736C7.10265 14.9366 7.06402 14.8705 7.06402 14.7951V11.6547V10.9516L6.39989 11.1824C5.99229 11.324 5.63625 11.4398 5.36493 11.5274C5.23272 11.5698 5.0836 11.5417 4.96858 11.4468L4.94306 11.4212L4.03783 10.516ZM11.2513 5.92078C11.6947 5.92078 12.1199 5.74465 12.4334 5.43113C12.7469 5.11761 12.9231 4.69239 12.9231 4.249C12.9231 3.80561 12.7469 3.38038 12.4334 3.06686C12.1199 2.75334 11.6947 2.57721 11.2513 2.57721C10.8079 2.57721 10.3827 2.75334 10.0691 3.06686C9.7556 3.38038 9.57946 3.80561 9.57946 4.249C9.57946 4.69239 9.7556 5.11761 10.0691 5.43113C10.3827 5.74465 10.8079 5.92078 11.2513 5.92078Z" stroke="white"/>
    <path d="M4.28516 8.6008C4.61996 7.77497 5.43688 5.8153 6.02614 4.58325M11.0482 9.40431L6.89663 11.2122" stroke="white"/>
    <path d="M3.91176 13.2941C3.91176 14.2363 3.14802 15 2.20589 15H2.20224H2.19857H2.19487H2.19116H2.18742H2.18366H2.17988H2.17608H2.17226H2.16841H2.16455H2.16066H2.15676H2.15283H2.14889H2.14492H2.14093H2.13692H2.13289H2.12885H2.12478H2.12069H2.11659H2.11246H2.10831H2.10415H2.09997H2.09576H2.09154H2.0873H2.08304H2.07876H2.07447H2.07015H2.06582H2.06147H2.0571H2.05272H2.04831H2.04389H2.03945H2.035H2.03052H2.02603H2.02152H2.017H2.01246H2.0079H2.00332H1.99873H1.99412H1.9895H1.98486H1.9802H1.97553H1.97084H1.96614H1.96142H1.95669H1.95194H1.94717H1.94239H1.93759H1.93278H1.92796H1.92312H1.91827H1.9134H1.90851H1.90362H1.89871H1.89378H1.88884H1.88389H1.87892H1.87394H1.86895H1.86394H1.85892H1.85389H1.84885H1.84379H1.83872H1.83363H1.82854H1.82343H1.81831H1.81317H1.80803H1.80287H1.7977H1.79252H1.78733H1.78213H1.77691H1.77168H1.76645H1.7612H1.75594H1.75067H1.74539H1.7401H1.7348H1.72948H1.72416H1.71883H1.71349H1.70814H1.70277H1.6974H1.69202H1.68663H1.68123H1.67582H1.6704H1.66498H1.65954H1.6541H1.64864H1.64318H1.63771H1.63223H1.62675H1.62125H1.61575H1.61024H1.60472H1.5992H1.59366H1.58812H1.58258H1.57702H1.57146H1.56589H1.56031H1.55473H1.54914H1.54355H1.53795H1.53234H1.52673H1.52111H1.51548H1.50985H1.50421H1.49857H1.49292H1.48727H1.48161H1.47595H1.47028H1.4646H1.45893H1.45324H1.44755H1.44186H1.43617H1.43047H1.42476H1.41905H1.41334H1.40763H1.40191H1.39618H1.39046H1.38473H1.379H1.37326H1.36752H1.36178H1.35604H1.35029H1.34454H1.33879H1.33304H1.32728H1.32152H1.31576H1.31H1.30424H1.29847H1.29271H1.28694H1.28117H1.2754H1.26963H1.26386H1.25809H1.25231H1.24654H1.24077H1.23499H1.22922H1.22344H1.21767H1.21189H1.20612H1.20035H1.19457H1.1888H1.18303H1.17726H1.17149H1.16572H1.15995H1.15418H1.14842H1.14266H1.13689H1.13113H1.12538H1.11962H1.11387H1.10811H1.10236H1.09662H1.09087H1.08513H1.07939H1.07365H1.06792H1.06219H1.05646H1.05074H1.04502H1.0393H1.03359H1.02788H1.02218H1.01648H1.01078H1.00509H0.999398H0.993714H0.988035H0.98236H0.97669H0.971026H0.965366H0.959711H0.954062H0.948418H0.94278H0.937147H0.93152H0.925899H0.920284H0.914675H0.909072H0.903476H0.897885H0.892302H0.886725H0.881155H0.875591H0.870035H0.864486H0.858944H0.853409H0.847882H0.842363H0.836851H0.831346H0.82585H0.820362H0.814882H0.80941H0.803946H0.798491H0.793045H0.787607H0.782178H0.776758H0.771348H0.765946H0.760553H0.75517H0.749797H0.744433H0.739078H0.733734H0.728399H0.723075H0.717761H0.712457H0.707163H0.70188H0.696608H0.691346H0.686096H0.680856H0.675627H0.67041H0.665204H0.660009H0.654826H0.649655H0.644495H0.639347H0.634211H0.629088H0.623976H0.618877H0.613791H0.608716H0.603655H0.598607H0.593571H0.588548H0.583539H0.578543H0.57356H0.568591H0.563635H0.558693H0.553765H0.54885H0.54395H0.539064H0.534193H0.529335H0.524492H0.519664H0.514851H0.510052H0.505269H0.5005H0.500005L0.500009 14.621L0.500017 13.2941C0.500017 12.352 1.26376 11.5883 2.20589 11.5883C3.14802 11.5883 3.91176 12.352 3.91176 13.2941Z" stroke="white"/>
  </svg>
        </div>
        <div class="usp__text">
          <p><span>Review Faster</span> by spawning fast Preview Environments for every Pull Request.</p>
        </div>
      </div>
      <div class="usp__container">
        <div class="usp__icon">
          <svg class="usp__svg" xmlns="http://www.w3.org/2000/svg"  viewBox="0 0 17 16" fill="none">
    <rect x="6.16406" y="0.500122" width="9.83581" height="11.6665" rx="2.5" stroke="white" stroke-linejoin="round"/>
    <rect x="1" y="3.83337" width="9.83581" height="11.6665" rx="2.5" stroke="white"/>
  </svg>
        </div>
        <div class="usp__text">
          <p><span>AB Test anything</span> from individual components to entire user experiences.</p>
        </div>
      </div>
      <div class="usp__container">
        <div class="usp__icon">
          <svg xmlns="http://www.w3.org/2000/svg" class="usp__svg" viewBox="0 0 17 16" fill="none">
    <path d="M8.5 1.5C4.91031 1.5 2 4.41031 2 8C2 11.5897 4.91031 14.5 8.5 14.5C12.0897 14.5 15 11.5897 15 8C15 4.41031 12.0897 1.5 8.5 1.5Z" stroke="white" stroke-miterlimit="10"/>
    <path d="M8.50043 1.5C6.68574 1.5 4.97949 4.41031 4.97949 8C4.97949 11.5897 6.68574 14.5 8.50043 14.5C10.3151 14.5 12.0214 11.5897 12.0214 8C12.0214 4.41031 10.3151 1.5 8.50043 1.5Z" stroke="white" stroke-miterlimit="10"/>
    <path d="M4.16699 3.6665C5.36199 4.51494 6.86637 5.02088 8.50043 5.02088C10.1345 5.02088 11.6389 4.51494 12.8339 3.6665" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
    <path d="M12.8339 12.3334C11.6389 11.4849 10.1345 10.979 8.50043 10.979C6.86637 10.979 5.36199 11.4849 4.16699 12.3334" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
    <path d="M8.5 1.5V14.5" stroke="white" stroke-miterlimit="10"/>
    <path d="M15 8H2" stroke="white" stroke-miterlimit="10"/>
  </svg>
        </div>
        <div class="usp__text">
          <p><span>Scale globally</span> as easy as you would with serverless but without all the limitations.</p>
        </div>
      </div>
    </div>
  </div>
</div>

Implementing the snippet in Ghost.io

Implementing the snippet in Ghost.io is super easy as well.

You just create a new HTML snippet element and paste in your finished code. Then, you simply hover over your snippet, click the button that looks like a post it which allows you to create a reusable HTML snippet and define a name. You will then find your snippet on the bottom of the list when creating a new block in Ghost.io.

This now left us with this beautiful reusable (and responsive) component:

Zero config cloud made for developers

From GitHub to deployment in under 5 seconds.

Sign Up!

Review Faster by spawning fast Preview Environments for every Pull Request.

AB Test anything from individual components to entire user experiences.

Scale globally as easy as you would with serverless but without all the limitations.

Styling issues in Ghost.io

One thing to note though is the implementation of the styling.

Usually, stylesheets are inserted into the head of the page. If you are only publishing your articles on a Ghost.io blog page, you can insert code in the head of either your global blog site or only the specific article page. Depending on how and where you want to use the snippet, inserting the code for your whole site is arguably the most convenient way. With a rising amount of snippets however, this will have the clients loading many styletags for unused components. In this case it would probably be better to insert the styletags per article.

To be able to transfer your snippets to a self hosted blog site, as well as avoiding the issue of either having to load all styletags globally or having to manually insert them for each article, you can implement the style tag into your HTML snippet. This is not the cleanest way to do it but it does make the use of snippets a lot more conventient.

Also, I think that sometimes you just have to work with the criteria you're given and if it works, it works:)

Conclusion

In this article, we looked at how we can use the new Figma Dev Mode to create an HTML element that can be used as a reusable snippet in Ghost.io.

I think that the Dev Mode already is a super neat and handy feature when it comes to styling. I'm sure the team over at Figma will continue to push updates to it to improve the experience.

Keep in mind that this only scratches the surface of what's possible with Figma Dev Mode. When working in a team, you can profit from better version control and GitHub integration as well as the VSCode plugin which does most of the styling job for you!

One thing I would love to see for it to be even more useful though, would be the implemation of design to HTML as opposed to only the CSS values. I could imagine, that the Figma team is already working on this, though.

In any way - I can't wait to see what will be coming next!