Jump to content

Dynamic CSS


MarkE
 Share

Recommended Posts

What approach do folks use when you want to dynamically set CSS? In particular, is there a preferred method when using Tailwind?

As far as I can see, the approaches are:

  1. Use in-line styles either in the host tag or in an in-line style tag. This is simple and straightforward to do but seems to be frowned upon by purists and is arguably a bit messy-looking.
  2. Use LESS (or similar). But this does not play well with Tailwind.
  3. Dynamically create a css file including css variables. But LESS is better at this.
  4. Create a php style file.

Are there performance issues with the last 2 approaches (or might they be overcome with caching).

The problem with Tailwind is that, while you can refer to php variables in your Tailwind class, because the tailwind output is compiled before the php is run, if the php variable value is not already represented by a value in the tailwind output css (perhaps because it has been generated somewhere else by a non-variable input) it will be ignored. This issue is making me think about ditching Tailwind and switching to LESS, but perhaps that is an overreaction.

Link to comment
Share on other sites

I have no idea how Tailwind works but when I need something like this I usually set a CSS variable and add them with the style attribute where needed.

Something like:

<?php namespace ProcessWire; ?>

<div style="--color: <?= $page->color ?>"><!-- My content --></div>

When I need something more complex, say a CSS animation depending on some of the page parameters (e.g. children count) then I output in a <style> element within my template.

  • Like 5
Link to comment
Share on other sites

The TailwindCSS JIT compiler scans the source code rather than the html output, so it's looking for full class names in your PHP code.  Hence you could do something like this:

<?php

namespace Processwire;

$bg = $page->bgSetting === "success" ? "bg-green-500" : "bg-red-500";
?>

<div class="mt-4 max-w-md <?= $bg ?>">
    Lorem ipsum dolor sit amet consectetur adipisicing
</div>

Or you could simply fake safelisting the expected values, e.g.  in a comment if you just have a few you want to make available in a template:

<?php

namespace Processwire;

$bg = $page->bgSetting === "success" ? "green-500" : "red-500";
/** safelist values: bg-red-500 bg-green-500 bg-blue-500 */
?>

<div class="mt-4 max-w-md bg-<?= $bg ?>">
    Lorem ipsum dolor sit amet consectetur adipisicing
</div>

As long as the full string of the class name is in the code, it will get compiled by TW (use spaces between if you're using this method though, as if you were adding classes directly).

(Of course there's also Tailwind's safelist setting in the tailwind.config file:  https://tailwindcss.com/docs/content-configuration#safelisting-classes)

Ian.

  • Like 1
Link to comment
Share on other sites

Thanks for the comments @monollonom and @iank. Very helpful!

22 hours ago, monollonom said:

I usually set a CSS variable and add them with the style attribute where needed.

I have used that approach, but forgot to mention it. It works well but, from a Tailwind point of view, it's pretty much like an inline style (except as noted below and probably with a bit of added overhead). In a typical case, I am setting an image width based on user input, so I can do (in Latte):

    <style>
        :root {
          --cardwidth: {$width};
          --cardheight: {$width};
          --imgheight: {$imgHeight};
    </style>

The tag is then:

<div class="[width:var(--cardwidth)] [height:var(--cardheight)]  ... etc...

Although this is a bit messy, it does at least have the advantage of being clear what is being set, as opposed to some arbitrary class name. To quote the Tailwind docs 

Quote

This is really like inline styles, but again with the benefit that you can use modifiers

-----------------------------------

21 hours ago, iank said:

The TailwindCSS JIT compiler scans the source code rather than the html output, so it's looking for full class names in your PHP code.  Hence you could do something like this:

I can't get this to work, at least not with the variable width example quoted above. It will correctly generate (say) h-[200px] as the class in the HTML but it is not in Tailwind's output css.

Similarly, class="[width:{$width}] ..... doesn't work - it seems it needs to be set as a css var first, although quite why that is, I'm not sure (See EDIT).

21 hours ago, iank said:

Or you could simply fake safelisting the expected values

That's neat! I wasn't aware of that. It works well if there is only going to be a limited set of options which, unfortunately, is not the case for the width/height example.

On balance, if I stick with Tailwind, it looks like css vars may be the way to go, but I'll do a bit more hacking about and, if I have any better ideas, will post them here.

----------------------------

PS - see the result here. The site editor can change the card size. It also gives the opprortunity of easily adding responsive variants.

----

EDIT: The reason why using a css custom property as an 'intermediary' for the variable works is that Tailwind can compile that (as var(--whatever)) to its output css, which happens before the php is interpreted to creat the css value which the html can then use.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...