The trick with CSS in TiddlyWiki?

You can avoid having to repeat the .className part of the selector by using this syntax:

.className {
   & someselector { someattributes }
   & someselector { someattributes }
   etc.
}

This is equivalent to:

.className someselector { someattributes }
.className someselector { someattributes }
etc.

and can save a lot of typing, especially when there are lots of CSS rules that are using the same .className for specificity.

-e

5 Likes

@EricShulman thanks for that, is the key here the & symbol effectivly replacing the need to start each with .className ?

Yes. I believe it can also be used with other CSS combinators such as “direct child” and “next-sibling”, like this:

.className {
   & > .someChildClass { ...}
   & + .someSiblingClass { ... }
}

which should be equivalent to:

.className > .someChildClass { ...}
.className + .someSiblingClass { ... }

Thanks eric I need to understand > and + before adding it to a design pattern

The design Pattern

So if using the <style> tags a good design pattern is in the tiddler do this;

<style>
.className {
   & someselector { someattributes }
   & someselector { someattributes }
}
</style>
  • And set the tiddlers class field to className

The styles will only apply if the tiddler containing the style tags is rendered (viewed) and one or more visible tiddlers have the class field = className

  • The CSS should not “bleed out” of this selected tiddlers or anywhere else.

Once you have a solution move the contents of the style tags to a tiddler tagged stylesheet, and alter the specificity if desired, or keep using class name.

Note: I recently proposed having wiki text symbols for a div where you can also apply a specific className to a bound part of a tiddler instead of a whole tiddler;

&&&.className

Everything in here has .className applied


&&&
  • This &&& is in contrast to @@ use @@ to search on tiddlywiki.com which is inline not block

&&& Generates

<div class="tc-div className"><p>Everything in here has .className applied</p></div>

Note: the following still needs clarification

The above is NOT redundant because although you can use;

@@.className
* Block content
* With one assigned class
@@

Will handle blocks but the class is applied to the first (or each?) tag;

<ul class="className"><li>Block content</li><li>With one assigned class</li></ul>

If you want to experiment I can provide the new wikiparser rule for &&& used above.

@@ also supports using a combination of direct attributes and classnames, like this:

<style>
.myClass { background:red; font-weight:bold; }
.bigText { font-size:2em; line-height:100%; }
</style>

@@.myClass.bigText
test1
@@

@@background:green;.myClass
test2
@@

“test1” will be big (as defined by .bigText) with bold text on a red background (as defined by .myClass).

“test2” will be normal sized bold text on a green background (i.e. the direct background:green attribute overrides the background:red attribute from .myClass)

-e

2 Likes

Good stuff @EricShulman now I wonder if we need to add some of this as guidence to tiddlywiki.com ?

  • There is already a lot of information at tiddlywiki.com about applying CSS styles and classes in TiddlyWiki but few that mention the use of the <style> tag which is perhaps an approach to designing CSS rather than applying it as a rule.
  • Perhaps it needs to be somewhere that we can capture design guidence, ways to support developing CSS not nessasarily the way its implemented. More of a playground?

Right. So.

What is the final best message to users?

Learn CSS and how TW can dynamically apply it too?

Is that a CSS lesson or a TW one?

You get my point?

What IS your trick?

One elaboration:

In that example, the &'s are unnecessary. This:

.className {
   someselector { someattributes }
   someselector { someattributes }
   etc.
}

means the same thing. While they are harmless here, using them probably leads to confusion. Because there are circumstances where there are used, and there, they are necessary.

To understand that we must note that the most common selector combinator is easy to ignore: the descendant combinator, which is represented simply with a space. These two selectors have very different meanings:

    div.my-class p    /* Selector 1        */

    div .my-class p   /* Selector 2 
       ^-------------- note the space      */

The first one represents all P elements that are descendant from a DIV element with the class “my-class”. Example A: <div class="my-class"><article><p>Includes me</p></article></div>

The second one represents all P elements that are descendant from any element with the class “my-class” that are themselves descendant from a DIV element. Example B: <div><article class="my-class"><p>Includes me</p></article></div>

Note the the Example A is not captured by Selector 2, nor is Example B captured by Selector 1. So the spaces make a big difference.

When the CSS grammar was expanded to include these nested selectors, the obvious syntax was easily able to capture Selector 2, but not Selector 1. Thus we can rewrite Selector 2 like this:

    div {
        .my-class p {...rules...}
    }

But there was no clear way to rewrite Selector 1. The & is meant to fill those gaps. With it we can write

    div {
        &.my-class p {...rules...}
    }

to mean the same thing as Selector 1. This is also useful for pseudo-classes such as :hover. For instance, this:

    a {
        text-decoration: none; 
        color: blue;
        &:hover {text-decoration: underline;}
        &.warning {
            color: red;
            &:hover {background-color: #fcc;}
        }
    }

Is equivalent to

    a {text-decoration: none; color: blue;}
    a:hover {text-decoration: underline;}
    a.warning {color: red;}
    a.warning:hover {background-color: #fcc;}

There is much more information on MDN.

3 Likes

This made me consider a little trick, one that turned out quite easy to do. I wrote a tiny procedure, css-here, which lets me add CSS that only applies to the current tiddler:

title: css-here
tags: $:/tags/Global

\procedure css-here(css)
<style>
div[data-tiddler-title="<<currentTiddler>>"] .tc-tiddler-body  {
<<css>>
}
</style>
\end

Note: updated to target only .tc-tiddler-body.

It would be used like this:

Other wikitext here...

<<css-here """
  /* your css here.  It will apply only to the current tiddler, 
     and only when directly rendered, not transcluded */
""">>

I only use in-tiddler stylesheets during initial development. I move them soon to one of my $:/tags/Stylesheet tiddlers. But this should make that initial development easier.

I don’t know if it will be useful for others. I’m not even sure if it will be useful for me, but I will play with it for a while to see.

css-here.json (248 Bytes)

4 Likes

Well I considered this thread trying to identify the best message, but I needed to rest on the skills of others with CSS as I am not an expert here.

It is about CSS and TW which is a unique environment.

  • You can learn how stylesheets work in tiddlywiki and follow the guidence
  • Understand the way CSS is deployed in TiddlyWiki and use this to play with CSS
  • Whilst developing using inline style tags with the guidelines under development here then migrate to stylesheet tiddlers as per @Scott_Sauyet @EricShulman and myself.

I get your point andf this thread is how we are addressing it.

Thanks @Scott_Sauyet this is a valuable reference, however rather than expand the posibilities, I would like us to determin a flexible but simple guidence for safely using the style tags when exploring CSS, and providing a simple path to implementing the result into stylesheet tiddlers.

If you can suggest what you think would be the best approach to provide guidence. For example not using the & allows the designer to then copy to the stylesheet tiddlers with little effort once verified aqs appropriate globaly;

   someselector { someattributes }
   someselector { someattributes }

note: I am very intentionaly refering to className and not introducing other tags because of the ease of introducing className to inline and block wikitext or html tags.

I am trying to “Keep it simple Sweetheart” although I have no problem seperatly “Dealing with complexity”.

This is great and interesting and may serve a purpose for someone writting lots of tiddlers with custom CSS (Eg a CSS tutorial) but is less strait forward to @EricShulman or your above simple suggestions.

I’m not sure what you want. I don’t know what general guidance would look like. For a confident CSS user, I might suggest simply starting with a style tag in the tiddler with the other rules wrapped in

div[data-tiddler-title="My Tiddler"] .tc-tiddler-body {

}

(And that is all my little helper does: automate the creation of the <style> tag and add such a wrapper, without having to directly enter the title.)

Then when the tiddler is ready, find an appropriate class name for any top-level elements in your markup, assign them that class name through HTML class attributes or @@.className ... @@ wrappers, and replace the div[data-tiddler-title="My Tiddler"] wrapper with one for that class name.

After confirming that everything still works, move that CSS from inline into a $:/tags/Stylesheet tiddler. Reconfirm, and you’re done; you can reuse that design elsewhere in your wiki now.

But that advice is for confident CSS users. If you’re looking for something for CSS newcomers, it would probably be very different, and I think I would have to understand what the purpose of this guidance is.

I actually think this is better with a widget that we can use in place of a style tag. This is my first time with a custom wikitext widget. They turn out to be quite easy!

\widget $local.style()
<style>
div[data-tiddler-title="<<currentTiddler>>"] .tc-tiddler-body  {
<$slot $name="ts-raw" />
}
</style>
\end

Used like this:

<div>Just a div <div>and its child div</div></div>

<$local.style>
div {padding: 1em; border: 1px solid black;}
</$local.style>

We can see that this applies only to the body of the current tiddler, and not its header and not the sidebar.

local.style Widget.json (275 Bytes)

5 Likes

Thanks @Scott_Sauyet but here I am interested not in targeting a single tiddler, although more often than not this can be done by only setting the class field on one tiddler. I am interested in being able to build a custom class, with the subselectors for any relevant selector.

  • Although elegant div[data-tiddler-title is still not readable to most people, works on a single hard coded title or needs the local style widget in the tiddler, and implies the div as the container.
  • If I read the prior comments this should be sufficent;
.className {
   someselector { someattributes }
   someselector { someattributes }
   etc.
}
  • In a stylesheet OR <style> tags
    Either inside the current tiddler, or if to be accessed from elsewhere use import or transclude.
  • Or set the tiddlers field class to className
  • Or just use className on a html tag of your choice via html class=
  • or .className in wikitext symbols.

In the above case to move this to a style sheet you can just copy the above CSS without the style tag to a tiddler tagged stylesheet, or add it to an existing one. If you want it to apply to the whole wiki remove the outer .className {..} and the selectors become global, and however selectivly they were designed.

I could see building an optional multi-line field for custom css that then gets applied only to the current tiddler. I will have to explore that. Bit like my local-viewTemplate field.

1 Like

You may use something like below:

[data-tiddler-title="my-tiddler"] {
   table, th, td {
      border: 3px solid purple;
   }
}
1 Like

I like this idea and would use it if I could figure out how to do it. Another textarea right underneath the main text field / editor before the type area with placeholder text of “Type the css for this tiddler” or something. Behind the scenes it just adds <style> content with the data-tiddler-title filter applied. It may not be best practice, but I like my “utility” tiddlers to be self-contained for easy moving between wikis.

Until I can figure that out, I like Scott’s widget idea and will implement that. Feels very logical.

Are you looking for guidance for yourself? Something had given me the impression that you were looking for general guidance we might add to the documentation. If it’s just for you, then you seem to have a handle on it already.1

If it’s guidance for others, then I really think we need to know something about the target audience.

If it’s for the general TW documentation, presupposing nothing about the users’ skills, then I would suggest that we don’t try at all the explain CSS directly, only to point to existing tutorials and reference documentation. There is simply no reason to cover any more than the bare basics of CSS in TW’s documentation. The only exceptions would be those things that make TW an unusual CSS environment:

  • Using the @@ ... @@ wrapper to apply CSS classes and CSS rules to some text
  • Avoiding CSS id selectors, which don’t work well in a transclusion-heavy environment
  • Putting CSS to apply across the wiki in tiddlers with the tag $:/tags/Stylesheet
  • Understanding that in-tiddler <style> tags apply across the wiki, but only when they’re rendered.

If this guidance is for experienced TW users looking to expand their understanding of CSS, then I would include that list, but add

  • Deeper explanations of how block vs inline styles work in CSS
  • A brief overview of CSS layout possibilities: floats, flexboxes, grids, and the like.

If this guidance if for experienced CSS users trying to apply their knowledge of CSS to TW, then I would include that list, but also add

  • An overview of the bits above about how to target certain CSS only at a particular tiddler
  • A deeper explanation for the ban on CSS ids

That’s news to me, and very interesting to hear!

Note that I updated my widget discussion to further extend this to div[data-tidder-title="My Title"] .tc-tiddler-body which is probably even less readable. The div at front is something I tend to do with my CSS, but could be skipped. The reason for my procedure and then my widget is so that people don’t have to understand that selector, only add a $local.style widget with their CSS.

While I could see that, my own usage of local css is only a rapid-development trick. It’s easier to edit the CSS in the same tiddler as the markup I want it to apply to. But it’s fairly rare that I end up with CSS I only ever want to apply to a specific tiddler. Personally, I would only use that as a temporary place to hang my styles while I get everything worked out, the same way I use my current technique, and will likely start using my local style widget.




1 Although I might argue that it’s often worth considering element.className as the root rather than just .className. Then we can target <p class="my-class"> differently from <ul class="my-class"> and both differently from <article class="my-class">, and can still put the common features in .my-class { ... }

1 Like

We are in furiuose agreement and you have elequently layed out what a we need to document for both naive and expierenced CSS users. Not as a CSS lesson but how CSS works alongside and within tiddlyWiki, Lets try and build on this thread and create some useful documentation.

If I do go back to the top of the thread, I was seeking support from people with detailed CSS knowledge to suggest/validate, I have got that and grateful, so let me have a go at converting the information given in my next reply.

  • A simple and robust way to experiment with CSS in TiddlyWiki