# How does it work? Who knows really? It's just magic for the most part. === ## Creating the dom tree Everything starts with the `body` element (by default). In your css, you can use `body` or `html` or `:root`. As long as your root (body by default) inherits that property, it's all good. ```css :root { --cssx-children: div#my-element; } ``` This will create a div inside `body` with the `id` (and `data-element` attribute) of `my-element`. Let's go deeper... ```css :root { --cssx-children: div#my-element; } #my-element { --cssx-children: header#div-a main#div-b; } ``` Now `my-element`, gets 2 children. You can probably figure out what those would look like. You may have already noticed a problem here. If you don't override the --cssx-children property, wouldn't all children of body get access to that? Well yeah, which is why, we have a `.cssx-layer` element between the parent and children. This element wraps all children and makes it so all the cssx property are unset. This can occasionally make styling a bit difficult but that's a YOU problem for trying to use this. ## Instances Instances are sort of like components. You can instantiate elements and provide them some custom properties. NOTE: Instances get unique ids so instances and children of instances cannot not use the id selector for the definition. ```css #my-element { --cssx-children: instance(div#user-card, map(--name: "Sugom Afart", --age: 20)) instance(div#user-card, map(--name: "Leeki Bahol", --age: 69)) instance(div#user-card, map(--name: "Yamam Aho", --age: 40)) ; } [data-instance=user-card] { --name: "default name"; --age: 0; --cssx-children: div#name div#age; } [data-element=name]::after { /* Using the ::after element to set content via css */ content: "Name: " var(--name); } [data-element=age] { /* Using the --cssx-text property because css doesn't like numbers in `content` */ --cssx-text: string("Age: ", get-var(--age)); } ``` ## Custom functions This is by far the most "fun" aspect of this project. Take a look at the docs for [call](./api/functions.md#call) for the api and examples. ```css #my-element { --factorial: func(--n: number) if(lte(get-var(--n), 1), 1, calc( get-var(--n) * call(--factorial, map(--n: calc(get-var(--n) - 1))) )); --cssx-on-mount: js-eval(string( 'console.log("', call(--factorial, map(--n: 5)), '")' )); } ``` > NOTE: `func` is noop and just exists for documentation. You can also do `func(--a: string, --b: number)` and it'll be valid syntax but ignored at evaluation. So basically, typescript. > NOTE: If you come at me with how using `js-eval` is cheating, I won't be responsible for your injuries. JS-in-CSS is the future. The way this works is that it creates a new dom element with `display: none` inside the caller (`#my-element`), which then becomes the scope for the function. Whatever arguments are passed to `call` will be added as css properties to this dom element. Then the expressions inside the function is evaluated within the context of that element. This means that with `call(--factorial, map(--n: 5))` the dom tree would look something like this. ```html