The trick with CSS in TiddlyWiki?

Folks,

I need some help from a CSS guru.

As you know most websites are single HTML pages, so any CSS in the <style>tag applies to the whole page. This is used in TiddlyWiki for the user Interface.

However more often than not we may be designing a tiddler where we want to use custom styles. If we use inside a tiddler the <style>tag it only applies when the tiddler is visible but it applies to everything in tiddlywiki, including all open tiddlers or the sidebar.

It is possible to set up conditional CSS according to tags and fields etc… but this is quite involved especially when you wish to add custom styles only in one tiddlers body.

Does anyone know a method I could use to make use of specific CSS in a specific tiddler body only?

For example rather than select through the use of class names or style="" I may wish to use this CSS;

table, th, td {
  border-bottom: 1px solid #ddd;
}

Whilst it targets all three tags table, th, td in one go, it will also tag all tables displayed in tiddlywiki.

How can I use this multiple tag assignment to be used in a single tiddler only without class or styles?

I can not see how to include the above and other CSS in a single class and add it to the tiddler class field.

Thanks in Advance

Post Script
If there is no mechanism to do this perhaps we can introduce one, a way that allows us to use “Native CSS” for a single tiddler, and ideally css which will be included if we export static html.

[data-tiddler-title=my-tiddler] table, 
[data-tiddler-title=my-tiddler] th, 
[data-tiddler-title=my-tiddler] td {
  property:property-value;
}

[data-tiddler-title^=prefix] div { ... } /* ^= starts-with */
[data-tiddler-title$=suffix] div { ... } /* $= ends-with */
[data-tiddler-title*=elloThe] div { ... } /* *= contains */
 

Thanks it looks like getting close.

So If I understand this just proceed the selector in the css with [data...] to target only the tiddlers meeting the condition?

Could the above be placed inside a style tag and then transcluded in the target tiddler, or directly in the target tiddler? ie no $:/tags/Stylesheet

Could we have data-tiddler-title=my-tiddler be data-tiddler-title=<<currentTiddler>> so as not to have to repeat entry?

Or should I use a tag or fieldname to have the styles able to apply to more than one tiddler (at a time) even if I start with one only?

1 Like

If you, on tiddlywiki.com, search for style you will see the tiddlers titled “Custom styles …” - you’ll see that you can style based on tags, title or class.

This technique is just a way to specify what to target and works because the rendered html code has these as attributes in the div by default, like so:

<div data-tiddler-title="HelloThere" data-tags="TableOfContents" ... >

I use this heavily and I believe we have @pmario to thank for its implementation.

BTW, recently there was an analogous addition to target tag pills with data-tag-title, i.e to style all, say, foo tag pills.

So, again, this is just a way to target something for css. You still need to put it in a stylesheet or in a styleblock… but there is a discrepancy that I just posted an issue about. I do typically get things to work after a while.

You can for example do the following:

tags: $:/tags/Stylesheet
type: (default - i.e not text/css)
text:
<$list filter='[[Hey there]]'>
[data-tiddler-title='{{!!title}}'] { border: 10px solid blue; }
</$list>
1 Like

Thanks all for the feedback.

@twMat so I could do this;

tags: $:/tags/Stylesheet
type: (default - i.e not text/css)
text:
<$list filter='[all[current]has[fieldname]]'>
[data-tiddler-title='{{!!title}}'] { border: 10px solid blue; }
</$list>

I am currently looking using three tiddlers to define a form for tiddlers than have a particular field value;

The Body template will not use the default but a tiddler of this basic structure.

A Layout tiddler, for the “myform”
$:/PSaT/forms/myform/layout

\import  $:/PSaT/forms/myform/macros
{{$:/PSaT/forms/myform/styles}}

then a set of html divs, spans section etc... containing as the content the various macros and with named classes (defined in the stylesheet.

As a result I have extended my use of styles to a set of named classes, so only these will have the styles applied. Also the macros used there in are not global but imported when needed.

so a tiddler with the conditions will transclude the the correct layout tiddler

Yes, that sounds doable. So to target things within the filtered tiddlers, you just “add” the targeting as usual in css e.g

[data-tiddler-title='{{!!title}}'] .tc-tiddler-body { border: 10px solid blue; }

1 Like

Here’s a neat css trick to shorten all of these css rules : using the :is selector :slight_smile:

[data-tiddler-title="{{!!title}}"] :is(table, th, td) {
  property:property-value;
}

:is([data-tiddler-title^=prefix],[data-tiddler-title$=suffix],[data-tiddler-title*=elloThe] 
) div{ 
... 
}
2 Likes

WHAT!!!? That was completely new to me and will be very useful! And accepted by basically all browsers. I thought such things were only possible in SASS and similar.


@TW_Tones - this issue discussion also has some good to know stuff. (Thank you Saq!)

2 Likes

Thanks @telumire.

Also, :not(), :where() and (soon) Cascade Layers (more here).

1 Like

I didnt knew about the layer at-rule, thanks ! Another CSS feature that I’m eager about is the CSS Container Queries, looks very promising

:is(), and :where() are almost identical except for the fact :is() raises specificity while :where() lowers it.

:not() is the inverse of :is().

Something else on the horizon is :has()

div:has(img) { ... }

Select (target) all divs that have img descendants.

1 Like

@layer the treatise: A Complete Guide to CSS Cascade Layers | CSS-Tricks - CSS-Tricks (@telumire)

2 Likes