1 min read

Conditional styles for Turbo Native in TailwindCSS

Joe Masilotti, in his Rails World 2023 talk, shows how to create custom styles for Turbo Native Rails applications in a way that does not break cache:

.turbo-native-hidden {
  display: hidden important!
}

app/assets/stylesheets/native.css

<head>
  <%= stylesheet_include_tag "application" %>
  <%= stylesheet_include_tag "native" if turbo_native_app? %>
</head>

app/views/layouts/application.html.erb

This works great for simple scenarios when I must show or hide certain elements. With Tailwind, however, I would like to benefit from the full richness of all its utility classes. 

How

In config/tailwind.config.js, add the following function to the plugins section:

  plugins: [
    # ...
    ({ addVariant }) => {
      addVariant('turbo-native', "html[data-turbo-native-app] &"),
      addVariant('non-turbo-native', "html:not([data-turbo-native-app]) &")
    },
  ]

config/tailwind.config.js

Next, add a conditional data attribute to your layout html tag:

<!DOCTYPE html>
<html <%= 'data-turbo-native-app' if turbo_native_app? %> >
<head>

In case the helper is not available in your views, add the following line to your application controller:

class ApplicationController < ActionController::Base
  helper_method :turbo_native_app?
end

app/controllers/application_controller.rb

And that's it! Now, you can use these variants to display your app on iOS/Android native app differently, from simple cases like:

<div class="flex turbo-native:flex-col">
</div>

To more complex scenarios:

<div class="flex non-turbo-native:group-data-[hide]:hidden turbo-native:flex">
  <%= render 'overdue_tasks_count', overdue_tasks_count: @overdue_tasks_count %>
</div>

Enjoy! I hope this helps (me remember).