djangotailwind-csshtmx

Tailwind color class not working in HTMX post result in a Django app


I want to send a form to a Django view via HTMX. After the request, a new span should be inserted in a div with the ID #result. This span has the Tailwind class text-green-500. This works so far (the span is inserted into the div). However, the color of the span does not change to the nice green tone that I expected.

This is the Django view:

@login_required
def create_daytistic(request: HttpRequest) -> HttpResponse:
    return HttpResponse('<span class="text-green-500">Daytistic erfolgreich erstellt</span>')

And this is the Django template:

{% extends 'base.html' %} {% block content %}

<div class="bg-gray-100">
  <div class="min-h-screen flex">
    <!-- Sidebar -->
    {% include 'components/common/sidebar.html' %}

    <!-- Main content -->
    <main class="flex-1 p-8" x-data>
      <div class="flex flex-row">
        <div
          class="bg-white p-6 rounded-lg shadow-lg w-1/2"
          x-data="{loading: false}"
        >
          <h1 class="text-2xl font-bold mb-4">Daytistic erstellen</h1>
          <p><b>Hinweis</b>: Die Daytistic darf maximal 4 Wochen alt sein.</p>

          <form
            hx-post="{% url 'daytistics_create' %}"
            hx-trigger="submit"
            hx-target="#result"
            hx-swap="innerHTML"
            hx-indicator="#spinner"
            @submit.prevent="loading = true"
            @htmx:afterRequest="loading = false"
          >
            {% csrf_token %}
            <label for="date" class="mt-4">Datum: </label>
            <input
              x-mask="99.99.9999"
              placeholder="DD.MM.YYYY"
              name="date"
              class="mt-4 bg-white-light text-gray-500 border-1 rounded-md p-2 mb-4 focus:bg-white-light focus:outline-none focus:ring-1 focus:ring-blue-500 transition ease-in-out duration-150 h-11"
            />

            <div id="submit-button-container" class="inline">
              <button
                type="submit"
                id="submit-button"
                class="h-11 w-48 bg-gradient-to-r from-lime-500 to-green-500 text-white font-bold py-2 px-4 rounded-md hover:bg-lime-800 hover:to-green-800 hover:scale-105 transition ease-in-out duration-200"
              >
                Neue Daytistic
              </button>

              <span id="spinner" class="hidden ml-4" x-show="loading">
                <span>
                  <div class="inline-flex flex-row gap-2 align-middle">
                    <div
                      class="w-4 h-4 rounded-full bg-green-600 animate-bounce"
                    ></div>
                    <div
                      class="w-4 h-4 rounded-full bg-green-600 animate-bounce [animation-delay:-.3s]"
                    ></div>
                    <div
                      class="w-4 h-4 rounded-full bg-green-600 animate-bounce [animation-delay:-.5s]"
                    ></div>
                  </div>
                </span>
              </span>
            </div>
          </form>
          <div id="result"></div>
        </div>
        <div class="bg-white p-6 rounded-lg shadow-lg w-1/2 ml-4">
          <h1 class="text-2xl font-bold mb-4">Tagebucheintrag erstellen</h1>
          <p><b>Hinweis</b>: Tagebucheinträge sind nur optional.</p>
        </div>
      </div>
    </main>
  </div>
</div>

<script>
  document.addEventListener("htmx:configRequest", function (evt) {
    document.getElementById("submit-button").classList.add("hidden");
    document.getElementById("spinner").classList.remove("hidden");
  });
  document.addEventListener("htmx:afterOnLoad", function (evt) {
    document.getElementById("submit-button").classList.remove("hidden");
    document.getElementById("spinner").classList.add("hidden");
  });
  document.addEventListener("htmx:afterRequest", function (evt) {
    if (!evt.detail.successful) {
      document.getElementById("submit-button").classList.remove("hidden");
      document.getElementById("spinner").classList.add("hidden");
    }
  });
</script>

{% endblock content %}

Those are my poetry dependencies:

[tool.poetry.dependencies]
python = "^3.12"
django-allauth = "^64.0.0"
Django = "^5.0.7"
django-widget-tweaks = "^1.5.0"
pytest-django = "^4.8.0"
faker = "^26.1.0"
pytest-factoryboy = "^2.7.0"
django-mathfilters = "^1.0.0"
django-tailwind = "^3.8.0"
django-htmx = "^1.19.0"
django-browser-reload = "^1.13.0"

My Tailwind config:


/**
 * This is a minimal config.
 *
 * If you need the full config, get it from here:
 * https://unpkg.com/browse/tailwindcss@latest/stubs/defaultConfig.stub.js
 */

module.exports = {
    content: [
        /**
         * HTML. Paths to Django template files that will contain Tailwind CSS classes.
         */

        /*  Templates within theme app (<tailwind_app_name>/templates), e.g. base.html. */
        '../templates/**/*.html',

        /*
         * Main templates directory of the project (BASE_DIR/templates).
         * Adjust the following line to match your project structure.
         */
        '../../templates/**/*.html',

        /*
         * Templates in other django apps (BASE_DIR/<any_app_name>/templates).
         * Adjust the following line to match your project structure.
         */
        '../../**/templates/**/*.html',

        /**
         * JS: If you use Tailwind CSS in JavaScript, uncomment the following lines and make sure
         * patterns match your project structure.
         */
        /* JS 1: Ignore any JavaScript in node_modules folder. */
        // '!../../**/node_modules',
        /* JS 2: Process all JavaScript files in the project. */
        // '../../**/*.js',

        /**
         * Python: If you use Tailwind CSS classes in Python, uncomment the following line
         * and make sure the pattern below matches your project structure.
         */
        // '../../**/*.py'
    ],
    theme: {
        extend: {},
    },
    plugins: [
        /**
         * '@tailwindcss/forms' is the forms plugin that provides a minimal styling
         * for forms. If you don't like it or have own styling for forms,
         * comment the line below to disable '@tailwindcss/forms'.
         */
        require('@tailwindcss/forms'),
        require('@tailwindcss/typography'),
        require('@tailwindcss/aspect-ratio'),
    ],
}

Template structure

➜  templates git:(fix/#59) ✗ ls -Ra
.:
.  ..  account  base.html  components  pages

./account:
.  ..  login.html  logout.html

./components:
.  ..  common  home

./components/common:
.  ..  footer.html  navbar.html  sidebar.html

./components/home:
.  ..  hero.html

./pages:
.  ..  daytistics  home

./pages/daytistics:
.  ..  dashboard.html  edit_daytistic.html

./pages/home:
.  ..  home.html  impressum.html  licenses.html

Interestingly it works with many other tailwind classes, for example text-blue-500, bg-green-500 or block.


Solution

  • If you are sure that Tailwind is loaded, but it does not apply to the dynamic span, try adding a global class in your CSS that ensures this class is present:

        @layer components {
      .text-green-500 {
        @apply text-green-500;
      }
    }
    

    To check if Tailwind is working, open the developer tools in the browser and check the styles applied to the span once it is inserted. Make sure there are no CSS conflicts or that it is not overwriting another rule.

    Alternative Solution

    As a quick test solution, you could add an inline style to the span to verify that the color is applied correctly:

    return HttpResponse('<span style="color: #10B981;">Daytistic erfolgreich erstellt</span>')
    

    If this approach works, the problem is probably related to the purging or configuration of TailwindCSS.

    Ensure that TailwindCSS is processing dynamic content

    The configuration you shared has the correct paths for the Django templates, but sometimes TailwindCSS does not recognize the classes if they are not in the HTML directly during compilation. To force Tailwind not to remove dynamic classes like text-green-500, you can make use of the following strategy:

    Force the inclusion of classes in the CSS: Add dynamically used classes in the CSS file or directly in tailwind.config.js so that they are not purged.

    Example of how to do this in the tailwind.config.js file:

        module.exports = {
        content: [
            // Template paths
            '../templates/**/*.html',
            '../../templates/**/*.html',
            '../../**/templates/**/*.html',
        ],
        theme: {
            extend: {},
        },
        plugins: [
            require('@tailwindcss/forms'),
            require('@tailwindcss/typography'),
            require('@tailwindcss/aspect-ratio'),
        ],
        safelist: [
            'text-green-500',  // Ensures that this class is never eliminated.
        ],
    }
    

    If with this check the color is applied correctly, the problem is definitely related to the TailwindCSS settings.

    These suggestions should help the Tailwind color to be applied correctly.