How can stylesheets access variables?

How can a regular stylesheet tiddler access currentTiddler and other contextual/dynamic variables (as opposed to e.g <<colour>> which is not contextual but global)?

I create quite a lot of stuff that rely on embedded styleblocks, for example;

<$list filter="red green blue">
<style>[data-tags*="<<currentTiddler>>"] {background:<<currentTiddler>>}</style>
</$list>

…however, embedding styles is brittle and adviced against, as Jeremy kindly and elaborately explains here.

The question has two sides (…I think): How can contextual variables be accessed by…

  1. Separate stylesheets
  2. Separate styleblocks

For (2), separate styleblocks, I guess the containing tiddlers title etc is accessible, which is at least something. But then even styleblocks are generally adviced against (for reasons I never quite understood but here is one issue caused by it).

A little reflection; When this question is phrased as “how can stylesheets access variables” one is perhaps led to only consider the stylesheets doing the action (presumably transcluding or calling the variable). But maybe the code using the style could instead send the variable to the stylesheet?

Thank you!

It would facilitate discussion a great deal if you could provide an example of a real world use case where you feel that you need this technique.

Thanks, but I use this a lot so unless you request a use case because you think my question is poorly formulated, I’d say I’m really asking for a general solution to the problem.

But even the (silly) examle in the OP, how could that be implemented with non-embedded styles? Let’s say the filter there is instead "[tag[colour]]" instead of hard coded, i.e:

<$list filter="[tag[colour]]">
<style>[data-tags*="<<currentTiddler>>"] {background:<<currentTiddler>>}</style>
</$list>

Thanks!

I requested a use case to better understand what you want to achieve and thus identify an appropriate solution, as I don’t see a generalized problem here that necessarily has a single definitive solution.

I would define a CSS rule that defines the background color for tiddlers tagged with colour, and then apply that CSS class to those tiddlers by means of a tiddler tagged with $:/tags/ClassFilters/TiddlerTemplate. You will find examples of this in the forum as well.

Other use cases might for examples require using CSS variables (custom properties) and setting those CSS variables via wikitext in the content where you want to use those styles.

Depending on the use case(s), there might be other options too.

OK, I didn’t realize there were so many different case variants. The thing I’m currently working on, which gave rise to the question, is a highly complex plugin where the embedded styles do work, AFAICT, so there is no immediate need, but it is a recurring problem I hit upon. I’ll release the plugin very soon and I’ll then ask if people have ideas for how to de-embed the styles.

$:/tags/ClassFilters/TiddlerTemplate

Ah, considering my heavy use of css, how have I totally missed this? Experimentation ahead.

I appreciate your input!

I don’t see how that’s going to work – at least, not in the way you’re hoping for. Where a given specificity is chosen, the browser will always choose the last one found (in source order).

/* Somewhere */
.my-class { background-color:red; }

/* Elsewhere */

.my-class { background-color:blue; }  /* WINS */

I’m not even sure @scope (when it becomes widely available) will help.

I think you want TW to “suddenly become” procedural (which it isn’t), and that CSS will somehow change its behavior to suit. Keeping this really simple: per render cycle, TW will read “everything” and build the HTML (including style blocks and stylesheets). The browser takes the HTML and creates the DOM. In there, is your CSS, wherein, the last definition found for any given selector is the one that wins. Said another way, all CSS is global (to the page) howsoever it was produced.

Having said that, I place variables and macros et al in my CSS, but never expect to have it swap in/out values “on the fly”. They’re effectively static and global.

Not sure any of this helps you, but that’s my take.

I read that, Mat. Mistakes aside, it still won’t work. Any time TW decides to “refresh”, you’ll get the last one found.

[how about this?]

If specificity is the reason you object: The premise for the OP is to outsmart that by using TW to create selectors that are very specific. For example, the data-tiddler-attribute already makes this possible, so to not e.g color all tiddlers backgrounds.

To show what I mean with “sending out contextual variables”, here’s a hypothetical examle, using the fictional $sendtostylesheet widget:

<$list filter="[tag[favourite]]">
<$sendtostylesheet
	$stylesheet=mystylesheet
	tid=<<currentTiddler>>
/>
</$let>
</$list>
title: mystylesheet
tags: $:/tags/Stylesheet
[data-tiddler-title="$tid$"] {background:"{{$tid$!!background}}"}

@twMat your ephemeral example is one that reminds me of the CSS custom properties approach that I mentioned earlier.

Example:

stylesheet:

.mystuff *{
    background: var(--bg-color);
}

wikitext:

<div class="mystuff">
    <$let mycolor="red">
        <span style=`--bg-color:$(mycolor)$;`>''Hello''</span>
    </$let>
</div>

Combined with fallback values and inheritance for custom CSS properties this can be very flexible. I use this approach a fair bit for UI components.

Of course. If that were my problem, I wouldn’t put it in a style block (in a <$list>). I’d put it in a regular stylesheet tiddler.

Nice! - but that is an embedded style. To give a still small “counter example”; Can you add a ::after pseudo element to it (showing, say, content:"x"). I think one needs a separate styleblock/sheet to do that.

I am afraid you have lost me there, I am not sure what it is you are asking for or what your objection is. I shared an example of using a variable from wikitext content in the stylesheet, as you requested. Note that the stylesheet and the wikitext work together and cannot be considered in isolation.

Ah, sorry, my point was just that there are some things that I don’t think can be solved using that method - but you of course already made that clear in previous posts, so, yeah, you’re right. CSS custom properties is a good idea when applicable, thanks :slight_smile:

Example of adding a ::after pseudo element with the content hi

stylesheet:

.mystuff *{
    background: var(--bg-color);
}

.mystuff span ::after{
    content: var(--content);
}

wikitext:

<div class="mystuff">
    <$let mycolor="red">
        <span style=`--bg-color:$(mycolor)$;--content:"hi"`>''Hello''</span>
    </$let>
</div>

The only real annoyance with using CSS custom properties is that you cannot use the style.* widget attributes. I keep forgetting this as I have it patched in my own wikis and need to submit a PR for it as some point.

2 Likes

Joyous.   

Very cool stuff! I had no idea that was possible. Thanks for showing us!

2 Likes

While it’s not specifically aimed at variables, those interested in this conversation may also enjoy reviewing this thread: How to use the colour macro as an attribute value - #9 by jeremyruston

In particular, wikitext can be used within a color definition, and (I can confirm) can also be pasted into the color field. (The standard color chooser makes this awkward to do, but you can overwrite the color field by “adding” a field named color, with the wikitext as its value.)

1 Like
  • This may be true in general.
  • Of note however, in tiddlywiki this is not 100% true, CSS can be present but not active by dint of not having the stylesheet tag, or being included in some way.
  • To some degree TiddlyWiki has a meta layer on top of html and CSS which can determine what is realised in the page.

OK, the real usecase is the just released static plugin.

The embedded styles prominently reside in the plugins core tiddler. As seen, they rely heavily on access to a few variables.

I have no idea how to achieve the result without the styles accessing those variables - which, AFAICT, means they must be directly embedded, or trancluded, into there.

If anyone has a working method to avoid the embedding, I’d appreciate it.

How did you go, did you solve this?

As I understand it some css stylesheets, containing variables, are wikified before use, thus can access the variables. For static representations you will need to do this before generating the static html, since the variables are not available outside tiddlywikis engin.