question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Variant nodes are appended to the document rather than a root

See original GitHub issue

What version of Tailwind CSS are you using?

3.0.16

What build tool (or framework if it abstracts the build tool) are you using?

postcss-cli 9.1.0

What version of Node.js are you using?

17.x

Reproduction URL

See the reproduction in 43081j/postcss-lit#26


postcss recently introduced the concept of a “document”. This allows custom syntaxes to be written for it which represent their arbitrary AST as the document, containing one or more Root nodes which are the actual CSS from said document.

For example, CSS in JS solutions would result in a Document representing the JS file, and one or more Root representing the contained stylesheets.

When combined with tailwind, this works like so:

  • postcss executes the custom syntax against the file, resolving to a postcss-compatible AST
  • postcss executes tailwind on this AST (Document { nodes: [Root, Root] } at this point)

Tailwind then executes code like this to replace the at-rules:

https://github.com/tailwindlabs/tailwindcss/blob/490c9dcb29bfed72855d701c40a7e04f69b5633b/src/lib/expandTailwindAtRules.js#L206-L209

This works because layerNode.base.parent is one of the child Root nodes. So by calling before, we’re prepending child nodes to the Root, not the Document (GOOD).

However, we can then reach this:

https://github.com/tailwindlabs/tailwindcss/blob/490c9dcb29bfed72855d701c40a7e04f69b5633b/src/lib/expandTailwindAtRules.js#L239-L241

Which, as you see, will append explicitly to root: the Document in this case.

This will result in an AST like so:

Document {
  nodes: [
    Root,
    Root,
    Rule, // BAD NODE!
  ]
}

When a custom syntax then attempts to stringify the AST back to the original non-css document, this misplaced Rule will be thrown on the end… causing a syntax error in the output.

Solution?

I don’t know tailwind’s source well enough to suggest a solution here. Possibly, if any layerNodes.* exists, use its parent as the root. If none exist, fall back to what it does now?

Or is there maybe an existing way to explicitly mark where those rules should exist? wherever layerNodes.variants comes from. Can we simply put some at-rule like @tailwindvariants?

Until this is fixed, custom postcss syntaxes can’t really work with “variant rules”.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:1
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
thecrypticacecommented, Feb 25, 2022

The fix for this will go out in the next release. What we’ve opted to do for now is run Tailwind on each “root” node present in the postcss Document node. This should place variants at the right spot based on where we see any @tailwind directives. Once related please do let us know of any issues you encounter with it!

1reaction
43081jcommented, Jan 25, 2022

awesome.

for tailwind maintainers: maybe its still worth warning in these situations? if someone tries to use one of your classes without specifying the at-rule, especially if they have a Document node, its probably not their intention to dump it on the end. In those cases it would be useful to have a warning somehow. If they don’t have a Document, no warning would be needed.

@ma-g-ma i’ll track it in the other issue we have open and try look into it soon 👍

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to change root of a node with DOMDocument methods?
In the DOM-Document model we can not change the property documentElement of a DOMElement object, so, we need "rebuild" the node... But how...
Read more >
root - CSS: Cascading Style Sheets - MDN Web Docs - Mozilla
The :root CSS pseudo-class matches the root element of a tree representing the document. In HTML, :root represents the <html> element and is...
Read more >
XPath and XQuery Functions and Operators 3.1 - W3C
This document defines constructor functions, operators, and functions on the datatypes defined in [XML Schema Part 2: Datatypes Second Edition] ...
Read more >
Working with Tree Model Nodes in Jackson - Baeldung
Alternatively, the get or with APIs can also be used instead of path. ... Our test supplies the root node of the JSON...
Read more >
Reference manual - ProseMirror
A state is a persistent data structure—it isn't updated, but rather a new ... Create a view. place may be a DOM node...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found