jonhmchan / descartes Goto Github PK
View Code? Open in Web Editor NEWDescartes | Write CSS in JavaScript
Home Page: https://descartes.io/slides
License: MIT License
Descartes | Write CSS in JavaScript
Home Page: https://descartes.io/slides
License: MIT License
Descartes looks like a great way to handle CSS. It would be really great if it could work with virtual DOM API's like: Inferno, Snabbdom, Virtual-DOM and others. Working with Decartes in Cycle.js would be especially awesome!
It took me days to find your site and I couldn't find it anywhere on Google search with lot of combination of "Javascript" and "CSS". On the last resort, I found HNAPP site that manage to find and I stil can't remember the name easily.
http://hnapp.com/?q=score%3E50%20css%20javascript
For the sake of getting enough exposure without difficulty to recall the name and pronunciation. You might want to change https://descartes.io to Carter or anything that is meaningful.
Extensions should be:
_
.transform
that manipulates the style tree before it is rendered by Descartes. Should take in the style tree as an argument and return a new style tree. This allows for custom rules, rule prefixing, etc.I've had an initial attempt with Plato.js
- you can see that within the src
for what this might look like.
If a web page's styles are all set by Descartes, what happens when JavaScript is disabled? Does the user just see unstyled text?
It seems to me that static styles could be generated server-side as a fallback for browsers that do not (or cannot) have JavaScript turned on.
This should include:
Really cool experiment, I tried to do the same the other way around; inserting scripts into CSS. However, I have something to note. This is not JSON:
new Descartes({
"html": {
"margin": 0,
"padding": 0,
"body": {
"margin": 0,
"padding": 0,
"section": {
"max-width": "800px"
}
}
}
})
It's just a javascript object (also noted as literal object). It'd be JSON if it was all a big string, but in this way it's just an object. See one explanation and [another](http://stackoverflow.com/a/2904181/938236 %28reason 3%29).
Right now, the library insists that any rules that have a high priority (furthest from the root) overwrite any styles that are applied to the node from lower priority rules. In other words, cascading does not work by default:
{
"h1": {
"color": "red",
"font-size": 36
},
"body": {
"h1": {
"color": "blue"
}
}
}
results in
<h1 style="color: blue;">
This is (currently) thought to be by-design. Descartes insists that we be explicit about our styles to avoid the complexity of our stylesheets as applications grow. Cascading can be done in a more controlled way by using mixins. It forces reused styles - especially for base elements - to be defined in a mixin and abstracted out. As the application scales, reusable code can get bundled together in a neat way:
var _h1 = {"color": "red", "font-size": 36}
{
"h1": {
"_mixins": [_h1]
},
"body": {
"h1": {
"_mixins": [_h1],
"color": "blue"
}
}
}
<h1 style="color: blue; font-size: 36px;">
However, there are some instances where this lack of cascade is problematic. Especially in the case of appended classes and psuedo-selectors:
"a": {
"text-decoration": "none",
"&.dark": {
"color": "#333"
}
}
We expect a.dark
to inherit the text-decoration: none
rule from its parent, but because it is nested within the element, it is ignored. Using mixins in this case seems unnecessary, and forces the developer to be too explicit at the element and class level.
Proposed Solution
Implement the cascade for rulesets that use the &
in its selector, such that it inherits the rules of its parent as a mixin. If there's a chain of &
-prefixed selector rulesets, the rules should cascade from the root to its grandchildren. This should result in cascading such that rules in a lower priority that conflict with the current ruleset will get overwritten.
A very common practice is to split styles into multiple files, typically so that certain parts are reusable throughout a site (like grids, fonts, etc.) and others are more specific in scope (styles for a specific page). There's currently no way for Descartes to handle multiple style trees at once, or to have some concept of merging multiple trees so that it cascades predictably. Currently, end users would have to merge the style trees on their own, then pass it into the constructor.
The approach we probably want to take is to have helper functions that merge multiple style trees into a single style tree with the correct prioritization.
Here's the specification we could take:
merge
that takes two arguments: tree
and target
tree
is typically the smaller style tree that is to be merged into the target
tree.target
should sensibly default to the Descartes style tree stored in this.tree
and initialized in the constructor. This allows for styles to be added to a Descartes instance incrementally.merge(A, B) === merge(B, A)
Currently, listeners affect the entire ruleset of a selector. For example, if you wanted to have every h1
tag have a random opacity every time you clicked it, it would like this:
h1 {
_listeners: [this, click],
opacity: function(_) {
return Math.random()
}
}
which in jQuery would be equivalent to:
$("h1").each(function() {
var _this = $(this);
_this.click(function() {
_this.css("opacity", Math.random());
})
})
This works well for very small examples like those above, but this becomes problematic if there are multiple event bindings and many, many rules that don't need to be computed:
h1 {
_listeners: [[this, click], [window, resize],
color: "red",
"font-weight": 300,
opacity: function(_) {
return Math.random()
},
"font-size": function(_) {
return (window.innerWidth >= 800) ? "2.0em" : "1.5em";
}
}
In the above example, opacity
changes when either the h1
is clicked or if the window is resized. Chances are, this second event binding is intended to just change the font-size
based on what is being used in the function, and vice-versa. There's no way to specify specific rulesets with specific event listeners. Descartes also reapplies static rules like the font-weight
and color
rules event when there is no change. It also makes it unclear how to set the default value of opacity
or font-size
on the initial load.
The proposed solution is to refactor the declaration of event listeners as a new property prefixed with a symbol like $
with the value as the ruleset to be computed upon the event firing. You should also be able to set a default that will be applied on initial load, with the function firing if there is no explicit default specified:
h1 { // No more `_listeners` arrays!
color: "red",
"font-weight": 300,
opacity: 1.0,
"$this.click": {
opacity: function(_) { // Does not fire on initial load, since `opacity` is specified already
return Math.random()
}
},
"$window.resize": {
"font-size": function(_) { // Fires on initial load, since there is no default `font-size` default
return (window.innerWidth >= 800) ? "2.0em" : "1.5em";
}
}
}
This is currently the achilles heel in using this library in a production environment. CSS (and the Less, and Sass that can generate it) get all the advantages of being optimized for the browser. Using just JavaScript here means Descartes can't exploit any of those optimizations: how can we improve the performance here? Here are a few ideas and considerations:
Want to hear people's thoughts.
Related to #26
Currently, Descartes does not take advantage of web workers to increase the performance of the library. I think the vast majority of what Descartes does should be done in background threads.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.