2

In a Rails 7 app with Tailwind CSS installed, I am using this form:

<%= form_with(model: project) do |f| %>
    <%= f.label :name, class: "some_tailwind_css_class" %>
    <%= f.text_field :name, autofocus:true, class: "some_other_tailwind_css_class" %>
    <%= f.submit class: "yet_another_tailwind_css_class"  %>
<% end %>

When there is no error in the form, the Tailwind CSS classes are triggered as expected, and the styles are perfectly applied to the HTML.

However, when the form throws a validation error (let's say: the name field is empty), I am unable to apply the Tailwind CSS classes for fields with errors (red border, red text for instance), given that the field_with_error class is nowhere to be found in the new.html.erb view file (as it is generated by the form helper instead).

I tried updating application.tailwind.css as follows, but I am unable to get that style triggered by the field_with_error classes in the HTML no matter what:

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
  .field_with_errors {
    label {
      @apply text-red-900;
    }
    input, textarea, select {
      @apply border-red-300 text-red-900 placeholder-red-300;
    }
  }
}

My concern is that, since Tailwind CSS scans the source code to determine what CSS to compile (or not, for that matter), it may not be "seeing" any HTML code actually containing field_with_errors, and is therefore not loading the custom CSS classes added to application.tailwind.css.

Is this not the way to proceed with Rails & Tailwind? Is there an error in the CSS I included in application.tailwind.css? Or is there another issue I am missing?

1 Answers1

3

the correct syntax should be

@tailwind base;
@tailwind components;
@tailwind utilities;

div.field_with_errors > label {
  @apply text-red-900;
}

div.field_with_errors > :is(input, textarea, select) {
  @apply border-red-300 text-red-900 placeholder-red-300;
}

problem is you try to modify base element instead component

you need to use @layer base instead @layer component the explanation are here

and also

because the .field_with_errors is added dynamically to the webpage

and tailwind css doing tree-shaking when compiling, it will try to remove all custom css that is not used

therefore .field_with_errors will be removed thus why the css is not applied

to make it stay we could declare the class without using @layer as per this guide

buncis
  • 2,148
  • 1
  • 23
  • 25
  • 1
    if its still doesnt work I think we need to make an issue in here https://github.com/rails/tailwindcss-rails, I will look more at this – buncis Aug 27 '22 at 08:44
  • I confirm that I had tried what you suggest, and just tried it again, and it is not working as expected. – newtoncolbert Aug 28 '22 at 08:57
  • 1
    I have update the syntax as per this example https://play.tailwindcss.com/RHN4KVctXG?file=css could u also test it ? – buncis Aug 28 '22 at 09:36
  • 1
    I have test it myself, remember to recompile the css or use incognito if its still not works – buncis Aug 28 '22 at 12:22
  • Thnaks. I updated code per your changes above, I stopped the server and started it again with `bin/dev`, and I tried in incognito mode: it still does not work. Could it be because fields have a class applied to them in the `_form.html.erb` partial they are generated from? `<%= f.text_field :name, autofocus:true, class: "appearance-none block w-full px-3 py-2 border border-gray-300 rounded-full shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" %>` I am wondering if that is overriding the `field_with_errors` style. But then how to fix it? – newtoncolbert Aug 28 '22 at 13:40
  • 1
    I think you should check on the inspect element if there is override happens it will showed there with a striped css and yes also I think class css have a higher priority than base css, try to use class css instead base css maybe? – buncis Aug 28 '22 at 13:58
  • `field_with_errors` is applied to the parent `div` around the `input`, so that may be the cause of the issue, since the class of the `input` seems to be taking priority over the class of the parent `div`. I am not sure how to work around that: maybe with some JS to remove the class from the `input` when `field_with_errors` is applied to the parent `div`? – newtoncolbert Aug 28 '22 at 14:16
  • 1
    yeah that is the expected behaviour https://guides.rubyonrails.org/active_record_validations.html#displaying-validation-errors-in-views there is also a way to override that, but I think its not supported anymore in current rails version, oh yeah also the code in top is not appending the class but replacing, if you delete ur input current class I think it should work if that is the case, then you just need to migrate the code from base to a class based ones `.field_with_errors > .text-field-class {bg-blue-900}` – buncis Aug 28 '22 at 14:42
  • ok, I will give it a try and let you know. – newtoncolbert Aug 28 '22 at 21:31
  • I make an issue here https://github.com/rails/tailwindcss-rails/issues/191 – buncis Aug 30 '22 at 10:13
  • 1
    hey I have update the solution @newtoncolbert – buncis Sep 16 '22 at 15:56
  • 1
    sorry for the late reply: yes, your updated solution worked. Thanks for your help. – newtoncolbert Oct 01 '22 at 12:33