Wish: Stylesheet - indicate which properties are (not) active

'twould be useful if…

stylesheets could show which style properties are overriden (and hence which ones are active), similar to what the inspector tool does.

image


The view mode for a static stylesheet tiddler is, after all, just an identical representation of the tiddlers underlying code which is a bit of a missed opportunity.


- Hey Mat, can’t you just look in the inspector tool?
- Well, no, that shouldn’t be necessary. If I open a stylesheet tiddler, it makes full sense to directly see what is actually active in it and what is not. This is not a matter of bug searching or developing, and any (non-advanced) user should see it. Besides, the inspector tool shows the styles for some specific element, it is not “a stylesheet” that is shown there.

1 Like

The problem is, that the stylesheet tiddler has no idea when it is active. CSS styles describe the presentation of the elements where they are applied to.

In the end it is the context that matters. eg: The following 2 rules describe

  • An element with the class=“test” should have a green outline
  • Elements within a “wrapper” element that are DIVs should have a red outline.
title: test-styles
tags: $:/tags/Stylesheet

.test {
  outline: 2px solid green;
  padding: 4px;
}

.wrapper div {
  outline: 2px solid red;
  padding: 6px;
}

Those 2 rules have no direct connection. With this information alone we cannot tell when and if those 2 rules are active. There needs to be the context of the HTML document, that puts the styling into action.

A tiddler: test-div-test

title: test-div-test

<div class="test">
Some text with a green border.
</div>

<p class="test">
Some more text with a green border
<p>

looks like this after the browser renders it. Both elements have the class test – they are green.

A second tiddler transcludes the first one.

title: test-div-wrapper

<div class="wrapper">
{{test-div-test}}
</div>

After rendering it looks like this:

So the same tiddler can have 2 different presentations, depending on the HTML structure. TW wikitext creates HTML text but the rendering is done by the browser, because they are good a it :wink:

Browsers compute the styling after rendering. TW wikitext has no idea about the calculated styles.

Only the browser knows when the styles are active depending on the DOM after the whole rendering is done.

Conclusion

The only way to see which CSS rules are active, are the dev-tools.


How can we predict if our CSS rules will be active.

Luckily, users have some “knobs” to “predict” the styling by using the “cascading” mechanism of CSS (Cascading Style Sheets) -

Where one rule says:

- Rules later defined in the file will overwrite rules defined earlier

TW provided some info about the “sort order” in the ControlPanel → Info → Advanced → Stylesheets section.

Where we can see, that my test-styles stylesheet has a very high chance, that the definitions are used. Because it is the last one in the list.

But still test-div-wrapper shows 2 different border colours, while test-div-test only shows 1 colour.


A second CSS rule says:

  • CSS rules with a “higher specificity” win, even if they are early defined in the file.

Specificity is a “beast” … A naive take could be: “The fancier the rule, the higher the specificity” – Which, off course, is completely wrong :confused:

Important: Specificity is a good thing too: We only have to define a rule with the same specificity as an other stylesheet and make sure it’s activated later in the list.

  • Specificity can be represented as a 4 digit number eg: 0,0,0,0
  • Where the different numbers are represented by different CSS types
    • digit 4. 0,0,0,1 is for element selectors eg: H1, DIV, P and so on
    • digit 3. 0,0,1,0 is for class selectors eg: .test, tc-btn-invisible
    • digit 2. 0,1,0,0 is for ID-selectors eg: #header-id
      • which we should avoid with TW, since IDs should only be used once per HTML page
      • Since tiddlers can be transcluded, we cannot guarantee that IDs are only shown once.
      • We only can guarantee, that they cause accessibility problems. Eg: with screen readers
    • digit 1. 1,0,0,0 is for inline styles

So it’s: <inline style>, <ID selectors>, <.class selectors>, <element selectors eg:H1>

And you can guess it. The specificity is “applied” from left to right. If a decision can be made using digit 1 the browser will ignore the other digits, no matter how high the numbers are

So inline styles win. That’s why we should be very very careful when using them, because others will have a hard time to overwrite “hardcoded” inline styles.

For TW we recommend to use “class based” specificity if possible. So if a button for example has 2 class definitions eg:

<$button class="tc-btn tc-btn-invisible" >test</$button> the specificity will be 0,0,2,0 if both classes are defined in a stylesheet and the DOM like this:

.tc-btn .tc-btn-invisible {
  	background: none;
	border: none;
}

So specificity can actually be “predicted” which may help to get better "hits"


11min Video about Specificiy

The best explanation I’ve ever seen is an 11 minute video: https://www.youtube.com/watch?v=CHyPGSpIhSs which will explain my “simplified” description in more detail.

And it should be easy to follow the video using TW editor and the preview pane.


There are some more CSS rules which are used a lot in TW vanilla/base CSS

hope that makes sense
-mario

PS: For those who prefer reading.

MDN info about CSS specificity
MDN Info about CSS inheritance

PPS: Avoid !important it’s toxic.

7 Likes

@pmario - yeah, I kind of figured it functions as you describe it. I’m thinking that just maybe it would be possible to either replicate the calculations that the browser does (that the inspector tool uses), or to piggyback by copying the calculated results and present them in the TW/stylesheet tiddler somehow…

(this is perhaps the best tl;dr of CSS Specificity I’ve seen in active memory! Thank you for your snappy attention to detail. :3 )

Hmm, You may remember, where the browser dev-tools actually came from. It was the famous “firebug-extension” initially developed for FireFox.

As seen at the linked website above the development started 2006 and ended with the “absorption of the tool” into browsers in 2017, where the browser vendors developed it even further, with low level access to browser internals.

So there was about 18 years of development that led us to a situation where we are now. That’s a lot of code


While writing the response above the line, I did some more investigation. It’s interesting :wink:

There are some javascript functions that let us access computed styles on a “per element / DOM node” level. It does give us some information about the applied CSS classes.

There also is a documents.styleSheets object accessible from within javascript.

  • So we would need to traverse the stylesheets and take every rule.selectorText
    • We need to traverse the DOM and check every element with element.matches(rule.selectorText)
      • If it matches the rule is a candidate - we need to store it in a tree like structure
        • We need to do this with every rule within the stylesheet. For tw-com it seems to be 707 rules
    • Once we have all the rule-candidates we need to:
  • Check inheritence within the DOM, which we would need to also “track” on the way up to the leaf nodes
  • Once we know all the info, we should be able to tell which “inhereted” and actual “selector defined” rules are assigned to the element.

That’s basically it. May be :wink:

Some code, which selects a single element: the “sidebar tabs list” and returns some info, that I cannot really interpret at the moment.

var elem = document.querySelector(".tc-sidebar-lists.tc-sidebar-tabs");
var  styleSheets = document.styleSheets;

for (var sheet of styleSheets) {
    for (var rule of sheet.cssRules) {
        if (elem.matches(rule.selectorText)) {
            console.log(rule, rule.cssText); // Log the matching rule
        }
    }
}

So it may be doable, but I personally prefer to use existing “wheels” instead of inventing them again.

On the other hand, there may be some valuable insight into the existing TW UI structure and the connected CSS rules.

just some thoughts
-mario

1 Like

Oooh, thanks for doing some Sherlock Holm’ing.

If I understand you description right, the first route would achieve what the OP requests but it would be very demanding and take a long time to execute, right?

Related: It would be interesting to see if every style defined in the stylesheets is actually used (and not overridden) in the standard distro. Would the same procedure be necessary to check this or is there some other way, perhaps even ready made tools, for this?

Yes, I occasionally find that even with the benefit of the browser’s inspector, I’m not able to track down where the active style lives (within which stylesheets or shadow tiddlers). Sometimes the inspector turns up a particularly useful string (a distinctive color code or odd measurement, or unusual class name), but sometimes it’s a time-consuming trial-and-error search.

So it’s worth asking: Do any of you more experienced TiddlyWiki-css experts have a reliable efficient way to work backwards from the inspector to isolate the tiddler responsible for this or that bit of active css?

Not sure about “expert”… well versed?

I use Firefox 99.99% of the time, so I can’t speak for chromium derived tooling.

  1. Start all of your style tiddlers like this:
/* 
  FILE: $:/Springer/css/my-stylesheet-blah (or whatever)
*/

.something { ...
  1. Select the element of interest in the Inspector.

  2. In the Styles panel you will see source line numbers where the css rules can be found:

When the line number is clicked…

  1. Now it’s a simple matter of scrolling back (up) to find the FILE comment:

image

I bet I perform these steps more than a dozen times each day. On a bad day, 4 dozen times :wink:

3 Likes

Indeed. Computer code can’t think.

Are you normal?
Just asking for Norman.
TT

Wow, your inspector — and those “inline” numbers — look totally different from the inspector tools I see in Chrome. Maybe I should go to Firefox next time I’m troubleshooting css, and see whether I can follow your suggestions there. Thanks!

I can of course add comments to my own stylesheets, although the fact is, most of the time when I’m trying to track down the cause of some detail, I can’t tell whether any of my own style tiddlers are involved at all, or whether some plugin or style setting from the core is responsible. Still, getting something like a line number is exactly the kind of leverage I’ve been thinking “must be possible somewhere”. So I look forward to trying it in Firefox, or discovering where it lives in google’s version.

I get it, totally. The steps I shared will stop that problem in its tracks.

It takes some diligence, of course, but “muscle memory” is the key here (what my other half prefers to call a “threshold concept” and getting past it).

I prefer it, obviously. But be aware, some of the detail may vary. My MO is perhaps a little different. As mentioned elsewhere recently, I have one stylesheet tiddler that transcludes everything tagged “css”, so I suspect all the "inline"s you see are due to that. Whatever. It’s all there somewhere and scrolling back//up to find the source is easy enough ← as long as you are using the comment thing, otherwise you’re right back where you started, overwhelmed by a mountain of css and “zero information”.

A few things I didn’t mention (referring to that first screen shot)

  • I like to embed debugging/dev info into the HTML (see the <debug> element)
      — I do that on steroids in my $log wrapper (also mentioned elsewhere recently)

  • Firefox tells you if there are event handlers attached to elements (see the event button). For JS devs, that’s quite useful. For TW folks, if your button or whatever is not responding and that little event button is missing, you at least know you broke something to stop TW wiring your button up properly.

  • You said “or whether some plugin or style setting from the core is responsible”. In the right-hand pane, “your stuff” should be uppermost. (If you add @layer tiddlywiki-defaults to the core stylesheets, they definitely will be.)

Same element, more detail…

We can see this context is stated clearly in the name CSS “Cascading Style Sheets”, the context is where you are in a set of cascades.

The whole value of CSS is this method, it lays on top of the HTML which contains the structure of the page and accesses the “content”, the cascading style sheets allow minimal code for very complex structures to have the styling applied.

  • TiddlyWiki renders TiddlyWiki Wikitext and TiddlyWiki Script (Procedures widgets etc…) to HTML and CSS adds to the presentation.

I am no expert either in CSS, however I “get it” conceptualy.

TiddlyWiki provides a structure you can leverage that reduces much of the complexity raise above in this thread.

In Settings > Info > Advanced > Stylesheets

  • CSS is applied in the order the stylesheets are listed below, the last one wins.
  • Clicking on the tag pill you can change the order.
  • Use different class names to those defined in the default CSS to avoid conflicts
  • As always dont use !important (It breaks the cascade)

I recommend writing css in such a way as to keep this mechanism effective and I don’t expect you to have many problems. You can always remove the stylesheet tag or reorder them to make adjustments.

True, but that order is only relevant for those rules which are already tied by specificity.

So in these three rules:

.my-group .my-node {color: red}
.my-group .my-section .my-node {color: green}
.my-section .my-node {color: blue}

the green rule would win, no matter in what order they were applied, because it has a higher specificity. If that one wasn’t there, then red and blue, which have the same specificity, would be chosen by the last-wins rule.

True, but this is just CSS doing what it does, cascade, with tiddlywiki we can reorder the stylesheets as we may in a webpage with an editor, leverage themes etc…

  • The value of understanding CSS and having informal “coding” rules to keep it simple, especially where overriding the core styles.
  • Eg dont use !Importiant, use one sheet and names for a particular target etc…
  • There is not too much that search and inspect cant solve.