CSS transitions

There’s some work I would like to do using CSS transitions (for instance, something like a card flip, but these would involve toggling class names of elements in the existing DOM. What I’ve seen of the TW model is to always regenerate HTML and never alter the DOM. Does TW have the capability to find HTML elements and add or remove classes on them?

https://tid.li/tw5/plugins-2019.html#%24%3A%2Fplugins%2Ftelmiger%2FFlippyCards

https://tid.li/tw5/test/flippy.html

@telmiger Flippy cards may be of some help.

Thank you. I’ll dig in and see how the transitions are triggered.

I figured that this must exist, although my search was related to transitions, not specifically flipping cards, which is precisely what I want!

I may not understand this but a new stylesheet listed at the end of the stylesheets will override previously defined CSS. Typically CSS is applied after all the HTML work. So you can redefine any existing CSS as desired. As long as you can identify the right selector(s). Some do this through the browser tools inspect.

1 Like

Feel free to ignore this, but if you want to know, the article I mentioned has a demo at sandpack-project - CodeSandbox. You can see the card turn over when you click the flip button. The code that does this is in the button handler, and it looks like this:

  front.classList.toggle('flipped')
  back.classList.toggle('flipped')

This simply adds the CSS classname “flipped” when it’s not already there, and removes it when it is. front and back are identically sized-and-placed HTML DIV elements, and the magic happens in the CSS:

.cardFront, .cardBack {transition: transform 0.5s;}
.cardFront {transform: rotateY(0deg);}
.cardFront.flipped {transform: rotateY(-180deg);}
.cardBack {transform: rotateY(180deg);}
.cardBack.flipped {transform: rotateY(0deg);}

When the flipped class is added to front, it changes from rotateY(0deg) to rotateY(-180deg). When flipped is removed, it changes back to rotateY(0deg). In both cases, there is a 0.5 second transition. (You can slow this down by changing the speed on line 34 to, say, 3.0s – it demonstrates the effect more clearly.)

This is the mechanism I was hoping to take advantage of. Looking at @telmiger’s Flippy Cards, it seems as though this is not necessary. My understanding was that the changed document is rebuilt and I would have thought that this would mean that such animations wouldn’t run. But the code, so far as I’ve read, seems to do the entirely normal HTML building I otherwise expect, but the transitions still run so I’m either misunderstanding CSS transitions or the Tiddlywiki model, or, quite possibly, both.

I’m hoping someone can pop up to explain what I’m missing, but it looks like @arunnbabu81 has supplied a model I can copy with or without understanding, or perhaps just use intact.

Some background that might be helpful:

In TiddlyWiki when you use an HTML tag, it is parsed by the wikitext parser and handled by the $element widget (which does not have any direct user affordances). The $element widget then creates the required DOM node. This is why you can use variables, text references and filtered transclusions for indirect assignment of the value of an HTML element’s attributes, just as you can with other widgets. When the value of an indirectly assigned attribute changes due to the TW refresh cycle being triggered by tiddler changes, the widget updates the DOM node’s corresponding attribute without destroying the DOM node or its children.

However, if a widget wrapped around the HTML tag needs to destroy and recreate itself as part of the TW refresh cycle, such as the $let widget when the value of a variable it assigns changes, then the contents of that surrounding widget are destroyed and recreated. In such a situation you will not get CSS animations as the DOM node is destroyed and re-created.

In TiddlyWiki an equivalent to that technique would look something like this:

<div class={{{ cardFront [[statetiddler]get[text]match[flipped]] :and[join[ ]] }}}>
<!--content here-->
</div>

Along with a button somewhere (which could be the card div itself using the $button widget to create the div) that toggles the value of the state tiddler between flipped and blank. Clicking the button would change the value of the state tiddler, which in turn would change the class assigned to the div.

I have only had a cursory glance at this but it seems like it uses the checked state of a checkbox along with an adjacent CSS selector to flip the card. As such, this is a pure CSS/HTML implementation that does not involve changes to any tiddlers and does not trigger the TW refresh process. Therefore the question of DOM elements being re-created never even arises. The downside with this approach is that if other user interaction triggers a refresh in the wiki, the state of the checkbox (and this the card) might not be preserved across the refresh cycle.

1 Like

Ah, then I did entirely misunderstand part of the rendering cycle. This is very useful information; thank you.

This is what I thought was universal. It’s nice to know that it’s not. It offers some useful possibilities.

For the case I’m considering, this would probably be an upside. The backs of the cards should be hidden most of the time. I might even consider only showing them while you hover or press them.


Mostly, I’m simply going to be storing away this information. It was something to research while I was stuck on another problem. That one is now cleared up, and I’ll go back to what I was working on. But I will be using this in a few weeks.

Thank you for all your help, @arunnbabu81, @TW_Tones, and @saqimtiaz!

2 Likes