PHP Code Dynamic Tailwind Classes Heads-Up!

I had been trying to figure out why my PHP code that creates a dynamic HTML table wasn’t styling the table correctly. What was even more confusing was that if I viewed the source in the browser and then copied the table definition and pasted it into tailwind Play it was working perfectly.

The reason is that tailwind is scanning the code before any php variables are resolved. In my case the PHP variables contained the required tailwind colour classes. Even though the resultant html code created by the php code was correct, because tailwind hadn’t seen the resultant code, it didn’t load the required CSS.

In my PHP code I am processing a collection which contains specifications (via the properties theme color selector) of the tailwind colour required by the table.

To get round this problem, I use an Elements @each command to loop down the Collection entries and create a hidden DIV that contains the classes for the required colours. Because, Elements processes the @commands on previewing / publishing, the tailwind classes are setup before tailwind scans the code and will therefore be resolved by tailwind.

This is an article that explains the issue: Just-in-Time friendly style variants in Tailwind CSS UI components

Anyway, I thought I would share in case anyone else hits the issue and needs to know how to resolve it. :slight_smile:

1 Like

You’re 100% correct! Elements builds Tailwind CSS on the fly, so we only output the classes in use on the page.

I should bookmark your post or add it to the Element Docs as this is bound to come up again in the future :blush:

Nice work!

Just a heads-up, I’ve added some information about this issue and the workaround in the Elements manual.

1 Like

@dan
Would be really great in the future if Elements scanned all setting values and passed them to tailwind’s Just In Time engine.

It does, but it can’t if the php hasn’t generated the classes yet and they are not on-page :roll_eyes: Read this article to understand more.

@bon is going to write-up some other more prefered solutions to this problem in the manual (hopefully later today).

I’ve updated the docs with a recommendation of adding the Tailwind classes you require to an HTML comment, rather than a hidden <div>. Better to have comments in your page, rather than adding additional, albeit hidden, DOM elements :slight_smile:

So this:

<!-- bg-red-500, text-center, w-1/2, h-full -->

is preferred to this:

<div class="hidden bg-red-500 text-center w-1/2 h-full"></div>
3 Likes

@bon From the documentation:

This comment is scanned by Elements when building Tailwind, so even though the classes are not directly rendered in the HTML, their styles will be generated and available to the HTML code generated by your PHP code.

Does Elements scan files that are in the backend folder that can be included into the index.php file in the templates folder? I have a suspicion that it doesn’t as I have an included PHP file that has lots of classes that don’t appear to be being resolved? I need to investigate more but thought I would check. :slightly_smiling_face:

I would need to double check this one, but I don’t think they are processed for tailwind classes.

I think you might need to rethink how your HTML is being included / generated to ensure the CSS is going to be generated correctly. I would not recommend using the comments approach for tailwind generation - that feels very prone to breaking, and not maintainable over the long term!

Generally, the approach should be that the HTML is generated in the templates directory, that way you can ensure the tailwind classes will be generated.

If you need to show/hide certain HTML I would recommend doing this via javascript - we are using alpine.js for dynamically / conditionally displaying content.

There are a few different approaches to achieve this, it really depends on your setup and user case. I’d be happy to give an example of how you could adjust your setup to work better in Elements, if needed :slight_smile:

@bon What about a dedicated json file in templates:

{
  "tailwind_classes": [
	"bg-blue-500",
	"text-white",
	"px-4",
	"py-2",
	"rounded-lg",
	"hover:bg-blue-700",
	"shadow-md",
	"font-bold",
	"text-gray-800"
  ]
}

If during testing a dev sees a class being added dynamically after page load
isn’t getting picked up, simply add to this “scanMe.json” file :man_shrugging:

that’s definitely an option.

We could allow a developer to add an array of “safe listed” classes - I think ideally we would hook in to the tailwind safelist feature that allows you to use a regex as it’d be rather tedious to have to list every single class you need.

Safelist doesn’t seem to be supported in v4 (not that Elements is on tailwind v4, yet), so it’ll be interesting to see if/how tailwind implements safelist in v4.

@bon

I’m rather new to Tailwind so hadn’t seen “safelist” but yeah, even better.

{
  "safelist": [
    "^bg-(red|blue|green)-500$",
    "^text-(white|black|gray)-700$",
    "^hover:bg-(yellow|pink)-300$"
  ]
}

check out the safelist docs for v3.

Not sure if they are planning on supporting that in v4 though :thinking:

I have worked around this particular issue by using @include and moving the included PHP file from the backend into the include folder.

A point to note is that if you leave in the <?php and ?> in the included file (which is preferable so you get all the PHP syntax formatting in the editor e.g. Nova) then you have to do something like this in your PHP code that is doing the including:

?>
@include("layout_array")
<?php

Turn off PHP, do the @include and the turn it on again.