TailwindCSS in Rails
Quick Reference
Category Classes
Layout flex , grid , container , mx-auto
Spacing p-4 , m-2 , px-6 , py-3 , space-x-4
Typography text-lg , font-bold , text-center , text-gray-700
Colors bg-blue-500 , text-white , border-gray-300
Sizing w-full , h-64 , max-w-md , min-h-screen
Flexbox flex , items-center , justify-between
Grid grid , grid-cols-3 , gap-4
Responsive md:flex , lg:grid-cols-4 , sm:text-sm
Installation
Rails 7+ with Tailwind
./bin/bundle add tailwindcss-rails ./bin/rails tailwindcss:install
Common Patterns
Container & Layout
<%# Max-width container %> <div class="container mx-auto px-4"> Content </div>
<%# Full-width section with max-width content %> <section class="w-full bg-gray-100"> <div class="max-w-7xl mx-auto px-4 py-8"> Content </div> </section>
Flexbox Layouts
<%# Horizontal flex %> <div class="flex items-center space-x-4"> <div>Item 1</div> <div>Item 2</div> </div>
<%# Space between %> <div class="flex justify-between items-center"> <div>Left</div> <div>Right</div> </div>
<%# Centered content %> <div class="flex items-center justify-center min-h-screen"> <div>Centered</div> </div>
<%# Vertical flex %> <div class="flex flex-col space-y-4"> <div>Item 1</div> <div>Item 2</div> </div>
Grid Layouts
<%# Basic grid %> <div class="grid grid-cols-3 gap-4"> <div>Column 1</div> <div>Column 2</div> <div>Column 3</div> </div>
<%# Responsive grid %> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <% @posts.each do |post| %> <%= render post %> <% end %> </div>
<%# Grid with different column spans %> <div class="grid grid-cols-12 gap-4"> <div class="col-span-8">Main content</div> <div class="col-span-4">Sidebar</div> </div>
Cards
<div class="bg-white rounded-lg shadow-md p-6"> <h3 class="text-xl font-bold mb-2"><%= @post.title %></h3> <p class="text-gray-600"><%= @post.excerpt %></p> <div class="mt-4"> <%= link_to "Read More", @post, class: "text-blue-500 hover:text-blue-700" %> </div> </div>
<%# Card with hover effect %> <div class="bg-white rounded-lg shadow hover:shadow-xl transition-shadow duration-300 p-6"> Content </div>
Buttons
<%# Primary button %> <%= link_to "Submit", path, class: "bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" %>
<%# Secondary button %> <%= link_to "Cancel", path, class: "bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded" %>
<%# Outline button %> <%= link_to "Edit", path, class: "border border-blue-500 text-blue-500 hover:bg-blue-500 hover:text-white font-bold py-2 px-4 rounded" %>
<%# Icon button %> <button class="bg-blue-500 hover:bg-blue-700 text-white p-2 rounded-full"> <svg class="w-6 h-6">...</svg> </button>
Forms
<%= form_with model: @post, class: "space-y-6" do |f| %> <div> <%= f.label :title, class: "block text-sm font-medium text-gray-700 mb-1" %> <%= f.text_field :title, class: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" %> </div>
<div> <%= f.label :body, class: "block text-sm font-medium text-gray-700 mb-1" %> <%= f.text_area :body, rows: 6, class: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" %> </div>
<div class="flex items-center"> <%= f.check_box :published, class: "h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" %> <%= f.label :published, class: "ml-2 block text-sm text-gray-900" %> </div>
<div class="flex space-x-4"> <%= f.submit "Save", class: "bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-6 rounded" %> <%= link_to "Cancel", posts_path, class: "bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-6 rounded" %> </div> <% end %>
Navigation
<nav class="bg-white shadow-lg"> <div class="max-w-7xl mx-auto px-4"> <div class="flex justify-between items-center h-16"> <%= link_to "Logo", root_path, class: "text-xl font-bold text-gray-800" %>
<div class="hidden md:flex space-x-8">
<%= link_to "Home", root_path, class: "text-gray-700 hover:text-blue-500" %>
<%= link_to "Posts", posts_path, class: "text-gray-700 hover:text-blue-500" %>
<%= link_to "About", about_path, class: "text-gray-700 hover:text-blue-500" %>
</div>
<button class="md:hidden">
<svg class="w-6 h-6">...</svg>
</button>
</div>
</div> </nav>
Tables
<div class="overflow-x-auto"> <table class="min-w-full bg-white border"> <thead class="bg-gray-100"> <tr> <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> Title </th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> Author </th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> Actions </th> </tr> </thead> <tbody class="divide-y divide-gray-200"> <% @posts.each do |post| %> <tr class="hover:bg-gray-50"> <td class="px-6 py-4 whitespace-nowrap"> <%= post.title %> </td> <td class="px-6 py-4 whitespace-nowrap"> <%= post.author.name %> </td> <td class="px-6 py-4 whitespace-nowrap text-sm"> <%= link_to "Edit", edit_post_path(post), class: "text-blue-500 hover:text-blue-700 mr-4" %> <%= link_to "Delete", post, method: :delete, class: "text-red-500 hover:text-red-700" %> </td> </tr> <% end %> </tbody> </table> </div>
Alerts/Flash Messages
<% flash.each do |type, message| %> <div class="<%= alert_class(type) %> p-4 rounded-md mb-4"> <div class="flex"> <div class="flex-shrink-0"> <%# Icon %> </div> <div class="ml-3"> <p class="text-sm font-medium"> <%= message %> </p> </div> </div> </div> <% end %>
<%# Helper method %> def alert_class(type) case type.to_sym when :notice, :success "bg-green-100 border border-green-400 text-green-700" when :alert, :error "bg-red-100 border border-red-400 text-red-700" when :warning "bg-yellow-100 border border-yellow-400 text-yellow-700" else "bg-blue-100 border border-blue-400 text-blue-700" end end
Modal
<div class="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full" id="my-modal"> <div class="relative top-20 mx-auto p-5 border w-96 shadow-lg rounded-md bg-white"> <div class="mt-3"> <h3 class="text-lg font-medium text-gray-900 mb-4">Modal Title</h3> <div class="mt-2"> <p class="text-sm text-gray-500">Modal content goes here.</p> </div> <div class="mt-4 flex justify-end space-x-3"> <button class="px-4 py-2 bg-gray-300 text-gray-800 rounded hover:bg-gray-400"> Cancel </button> <button class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"> Confirm </button> </div> </div> </div> </div>
Badges
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800"> New </span>
<span class="inline-flex items-center px-3 py-1 rounded-md text-sm font-medium bg-green-100 text-green-800"> Published </span>
Responsive Design
<%# Hide on mobile, show on desktop %> <div class="hidden md:block"> Desktop only </div>
<%# Show on mobile, hide on desktop %> <div class="block md:hidden"> Mobile only </div>
<%# Responsive text sizes %> <h1 class="text-2xl md:text-4xl lg:text-6xl font-bold"> Title </h1>
<%# Responsive padding %> <div class="p-4 md:p-8 lg:p-12"> Content </div>
Customization
// config/tailwind.config.js module.exports = { content: [ './app/views//*.html.erb', './app/helpers//.rb', './app/assets/stylesheets/**/.css', './app/javascript/**/*.js' ], theme: { extend: { colors: { 'brand': { light: '#3fbaeb', DEFAULT: '#0fa9e6', dark: '#0c87b8', } }, fontFamily: { sans: ['Inter', 'sans-serif'], }, }, }, plugins: [ require('@tailwindcss/forms'), require('@tailwindcss/typography'), ], }
Best Practices
-
Use @apply sparingly - Prefer utility classes in templates
-
Create components for repeated patterns
-
Use responsive prefixes - mobile-first approach
-
Leverage Tailwind plugins - forms, typography, etc.
-
Keep custom CSS minimal - use Tailwind's configuration
-
Use consistent spacing scale - stick to theme spacing
-
Optimize for production - PurgeCSS removes unused styles automatically
Common Pitfalls
-
Too many utilities - Extract to components or use @apply
-
Not purging - Make sure content paths are configured correctly
-
Fighting the framework - Use Tailwind's patterns, don't fight them
-
Forgetting responsive - Always test mobile-first
References
-
Tailwind CSS Documentation
-
Tailwind CSS Rails
-
Tailwind UI Components