April 08, 2022

Tailwind CSS - How To Integrate Into ButterCMS (or other Headless CMS)

Doug Breaker

Author

TailwindCSS - Perfect for A Non-Professional Developer Like Me

Man, do I love Tailwindcss. I think I love it so much because I never took the time to property learn CSS and the whole, "really separate everything" idea of completely removing styling from the html code. By no means am I professional developer. I coded professionally as a back-end, SQL-centric developer for about 5 years way back in the early 2000's, but since then I've always held various business jobs. I limped along and could build decent looking sites, but always flopping back and forth between html and css files really slowed me down. As a backend developer I never learned CSS, and once I switched into non-coding jobs I never took the time to get good enough at CSS to really crank away when I coded.

Enter Tailwind!  I love it.  After a few hours of tutorials and getting up to speed I can now fly when I code.  I usually start by building a theme with Shuffle.dev (love that tool), apply that, then tweak and modify my tailwind code on the fly.  Fast, efficient, glorious.

ButterCMS - A Killer Headless CMS Ultra-Friendly To Developers

For content management, I always turn to ButterCMS. Sure, their founder Jake and I used to work together, but that aside Butter offers a crazy-powerful, super-simple headless CMS that takes just a few minutes to integrate into Rails (my poison of choice).  Need a blog?  No problem, dive into Butter's 20 minute tutorial and BAM!, your site is the proud new owner of a blog.  Need landing pages?  POW!, a few more minutes in Butter and you can create landing pages on the fly, right from Butter.  I enjoy it so much that I've used for both personal sites - LostPropertyFinder.com, SQLBot.co, and CheckDeposit.io, and for companies I've worked at - EarthClassMail.com, Scripted.com and now MDHearingAid.com.

Uh Oh!  How Can I Apply Tailwind Classes to HTML Spit Out By ButterCMS (or Any Headless CMS)?

If you're anything like me as a developer, you may forget to think things through all the way to the end. That happened to me when building this site. I am building that site with Rails/Tailwind and got to the point of building the blog with ButterCMS when I hit one of those, "Uh oh, I didn't think about that" problems.

What was the issue?  Tailwind depends on adding classes to your html elements like this:

<h2 class="text-4xl md:text-5xl my-2 font-bold font-heading">

However, when you put html that comes out of ButterCMS on your page, all you get is pure HTML like this:

<h2>

Ruh roh raggy, how can we fix that?

I shot my man Jake at Butter a note, and he gave the excellent suggestion of this:

I would try to set some CSS rules more globally to control how <p> is styled for your blog posts.  Something like wrapping in a blog_body div and then set styles on that div that get globally applied. This will save you from having to manually apply the "class" tags to all of your blog post paragraphs in Butter and you can just use the editor in WYSIWYG mode.

.blog_body > p {
 // the same styling attributes as "mb-6 leading-loose text-blueGray-400"
}

<div class="blog_body>
 // All your butter post HTML here (which includes p tags, etc)
</div>

 I gave that a swing, but it still didn't feel right, and I found myself doing that old, dreaded tango of flipping back and forth between CSS files and my view files again.  Argh.  After some frustrating minutes, I came up with a better solution. Better you say?  Perhaps it's not the cleanest, but for me it keeps me in the view code where I belong, and I don't have to figure out all the CSS info and plug that into my CSS files.  So what is it?

Pretty simple - just build a helper to add in the right Tailwind classes to the html code coming out of butter as we process the view.  Here's my helper code:

  def add_tailwind_classes(html_safe)
    #do simple gsubs to replace the element tags we care about with our styles
    html_safe.gsub!('<p>','<p class="mb-6 leading-loose text-blueGray-400">')
    html_safe.gsub!('<ul>','<ul class="list-disc list-outside pl-5">')
    html_safe.gsub!('<li>','<li class="mb-2">')
    html_safe.gsub!('<h1>','<h1 class="text-5xl mb-2 leading-tight  ...">')
    html_safe.gsub!('<h2>','<h2 class="text-4xl mb-2 leading-tight ...">')
    html_safe.gsub!('<h3>','<h3 class="text-3xl mb-2 leading-tight  ...">')
    html_safe.gsub!('<h4>','<h4 class="text-2xl mb-2 leading-tight  ...">')
    html_safe.gsub!('<img src','<img class="shadow-lg rounded  ...')
    html_safe.gsub!('<figcaption>','<figcaption class="mb-10  ...">')
    html_safe.gsub!('<a ','<a class="underline text-blue-400" ')
    
    html_safe
  end

 

And here's my views/buttercms/post/show code:

    <div class="mx-auto">
      <%= add_tailwind_classes(@post.body.html_safe).html_safe %>
    </div>

Elegant?  Perhaps not.  Effective?  You bet your bananas.

But Wait!  There's An Even Better Way!

After writing this I asked Reddit for advice on this approach, and it turns out Tailwind offers a super-simple, easy solution to this problem.  Using the Typography plugin applies great-looking styling to a chunk of standard HTML, see the example here, and the full documentation here.  Using the plugin is as simple as adding a "prose" class to the containing element, as shown here:

    <div class="mx-auto prose">
      <%= @post.body.html_safe %>
    </div>

The plugin allows you to add in your own custom treatments for any standard HTML element, see example below.

    <div class="mx-auto prose prose-figcaption:text-center prose-figcaption:italic prose-img:shadow-lg prose-img:rounded">
      <%= @post.body.html_safe %>
    </div>

This offers a wonderful way to use Tailwind with a headless CMS.  Kudos to the Tailwind team. 

Conclusion

TailwindCSS is a newfangled way to bring CSS back into HTML in a cool, modern way.  ButterCMS offers a fantastic headless CMS.  Hopefully my solutions above offer a simple way to let these two amazing tools get married and love happily ever after.

 

married
TailwindCSS and ButterCMS, a Happy Couple

© %= Time.now.year %> . All rights reserved.