Use when applying Tailwind CSS styling to Rails views. Uses utility classes, responsive design patterns, and integrates with Rails view helpers.
Limited to specific tools
Additional assets for this skill
This skill is limited to using the following tools:
You apply Tailwind CSS styling to Rails applications. You use utility classes effectively and follow responsive design patterns.
# Verify Tailwind is installed
cat config/tailwind.config.js
cat app/assets/stylesheets/application.tailwind.css
Link helpers:
<%= link_to "Home", root_path, class: "text-blue-600 hover:text-blue-800 underline" %>
<%= link_to users_path, class: "inline-flex items-center px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700" do %>
<svg class="w-4 h-4 mr-2">...</svg>
View Users
<% end %>
Form helpers:
<%= form_with model: @user, class: "space-y-6" do |f| %>
<div>
<%= f.label :email, class: "block text-sm font-medium text-gray-700" %>
<%= f.email_field :email, class: "mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500" %>
</div>
<div>
<%= f.submit "Save", class: "w-full px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2" %>
</div>
<% end %>
Flash messages:
<% flash.each do |type, message| %>
<div class="<%= flash_class(type) %> p-4 rounded-md mb-4">
<%= message %>
</div>
<% end %>
<%# Helper %>
<%
def flash_class(type)
case type.to_sym
when :notice then "bg-green-100 text-green-800"
when :alert then "bg-red-100 text-red-800"
else "bg-blue-100 text-blue-800"
end
end
%>
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<%= yield %>
</main>
<div class="bg-white shadow rounded-lg overflow-hidden">
<div class="px-4 py-5 sm:p-6">
<h3 class="text-lg font-medium text-gray-900">Card Title</h3>
<p class="mt-2 text-sm text-gray-500">Card content goes here.</p>
</div>
</div>
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
<%= render @items %>
</div>
<div class="space-y-6">
<div>First item</div>
<div>Second item</div>
<div>Third item</div>
</div>
<%# Primary %>
<button class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
Primary
</button>
<%# Secondary %>
<button class="px-4 py-2 bg-white text-gray-700 border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
Secondary
</button>
<%# Danger %>
<button class="px-4 py-2 bg-red-600 text-white rounded-md hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2">
Delete
</button>
<input type="text"
class="block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm"
placeholder="Enter text...">
<%# With error %>
<input type="text"
class="block w-full rounded-md border-red-300 text-red-900 placeholder-red-300 focus:border-red-500 focus:ring-red-500 sm:text-sm">
<p class="mt-2 text-sm text-red-600">This field is required.</p>
<nav class="bg-white shadow">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<div class="flex">
<%= link_to root_path, class: "flex items-center" do %>
<span class="text-xl font-bold text-gray-900">Logo</span>
<% end %>
<div class="hidden sm:ml-6 sm:flex sm:space-x-8">
<%= link_to "Dashboard", dashboard_path, class: "inline-flex items-center px-1 pt-1 border-b-2 border-blue-500 text-sm font-medium text-gray-900" %>
<%= link_to "Users", users_path, class: "inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700" %>
</div>
</div>
</div>
</div>
</nav>
<div class="overflow-hidden shadow ring-1 ring-black ring-opacity-5 rounded-lg">
<table class="min-w-full divide-y divide-gray-300">
<thead class="bg-gray-50">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Name</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Email</th>
<th class="relative px-6 py-3"><span class="sr-only">Actions</span></th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<% @users.each do |user| %>
<tr>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900"><%= user.name %></td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"><%= user.email %></td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<%= link_to "Edit", edit_user_path(user), class: "text-blue-600 hover:text-blue-900" %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
Use breakpoint prefixes: sm:, md:, lg:, xl:, 2xl:
<%# Mobile-first: stack on mobile, side-by-side on larger %>
<div class="flex flex-col md:flex-row md:space-x-6">
<div class="w-full md:w-1/3">Sidebar</div>
<div class="w-full md:w-2/3">Main content</div>
</div>
<%# Hide on mobile %>
<div class="hidden md:block">Only visible on md and up</div>
<%# Show only on mobile %>
<div class="md:hidden">Only visible on mobile</div>
<%# Enable in tailwind.config.js: darkMode: 'class' %>
<div class="bg-white dark:bg-gray-800 text-gray-900 dark:text-white">
Content
</div>
Create view helpers for repeated patterns:
# app/helpers/tailwind_helper.rb
module TailwindHelper
def btn_primary(text, path, **options)
link_to text, path, class: "px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 #{options[:class]}", **options.except(:class)
end
def card(&block)
content_tag :div, class: "bg-white shadow rounded-lg p-6", &block
end
end
After styling: