-
Notifications
You must be signed in to change notification settings - Fork 20.5k
CSS: Support custom properties, #3144 #3199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CSS: Support custom properties, #3144 #3199
Conversation
src/css.js
Outdated
| } | ||
|
|
||
| function isCustomProperty( value ) { | ||
| return value.match( /--(.*)/ ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few remarks:
- This will match things like
a--b; you should check that the string starts with--, not just contains it. - Why did you introduce the group
(.*)? You don't use it anywhere. - It's better to change that to
/^--.*/.test( value )` as you only care about it matching or not and what you wrote will return the array with matches; the browser has better chances of optimising the former.
|
This PR adds 47 bytes (minified+gzipped). That's not a negligible amount. We should explore whether it wouldn't be better to just use the |
|
@ConnorAtherton Would you like to try to run some performance tests? You can see my example template in one of my PRs. |
|
@mgol Thanks for looking at this. All your comments are valid and I will rework my additions based on your feedback. Thanks for providing the link to your benchmarks in your other PR, I will update this thread with similar metrics in the coming days. I like the idea of using |
|
Following on from my previous comment, I have benchmarked both methods for adding styles to a DOM node. Here is my benchmark (I think this would be a useful template to add to the repo for future PRs) followed by the results: <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>A page for perf tests</title>
<style>
/**
* Any styles for perf start state
*/
</style>
</head>
<body>
<div id="test-div"></div>
<script src="http://code.jquery.com/jquery-git.js"></script>
<script>
var $j = jQuery.noConflict();
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/2.1.0/benchmark.js"></script>
<script src="../dist/jquery.js"></script>
<script>
var suite = new Benchmark.Suite;
var currentVersion = $j('#test-div');
var newVersion = $('#test-div');
// add tests
suite
.add('Adding styles using object assignment', function() {
currentVersion.css('--color', 'blue');
currentVersion.css('--color');
})
.add('Adding styles using setProperty', function() {
newVersion.css('--color', 'blue');
newVersion.css('--color');
})
// add listeners
.on('cycle', function(event) {
console.log(String(event.target));
})
.on('complete', function() {
// So we can inspect the results ourselves in the console
window.s = this;
console.log('Fastest is ' + this.filter('fastest').map('name'));
})
// run async
.run({'async': true});
</script>
</body>
</html>Chrome 51: Firefox 49: Safari 9: IE WIP |
|
It's definitely slower, especially in Firefox for some reason, but I don't think it is too slow. Focusing on Firefox, 15,000 ops per second is one op in 66 microseconds. How many CSS properties would typical code set in a 16ms frame? Also, setting properties often causes reflow which would be a lot more expensive than the act of setting the property. |
Totally, should be fine |
src/css.js
Outdated
| } | ||
|
|
||
| function isCustomProperty( value ) { | ||
| return /^--.*/.test( value ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We usually put definitions of regexes in the beginning of the module with r prefix, like -
Line 36 in 02c5e29
| rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, |
Could you maybe do the same and also get rid of the isCustomProperty function and just use /^--.*/.test(...) directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, but the regex might as well be /^--/.
|
Thanks for doing the benchmarks, @ConnorAtherton! The numbers look good so I'd go with just always using As an added bonus, we might get https://bugs.jquery.com/ticket/14394 fixed as a side-effect. :-) You could use a test from my PR (that had to be reverted later): |
src/css.js
Outdated
| style[ name ] = value; | ||
| } | ||
| if ( customProperty ) { | ||
| style.setProperty( name, value ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering, why we can't always use setProperty?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, i see, i missed discussion :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we can use setProperty here because properties like maxWidth and marginRight don't work. I've delayed working on this because I keep running into this issue but according to the spec, and please correct me if I'm reading this wrong, camel-cased properties aren't transformed into their CSS equivalents, only converted to ASCII lowercase. Every test that fails when I switch to setProperty for every property is precisely because of this.
Sources:
That would be cool! But can we do this in separate PR? |
|
Hey all, thanks for the feedback. Apologies for the delay with this, I'm currently on vacation. Going to work on this more today. |
|
@ConnorAtherton That's expected. Regular CSS properties can be read or set using regular property access but CSS variables can't, you have to use Do you know what needs to be done to finish this PR? |
test/unit/css.js
Outdated
| assert.equal( jQuery( "#customPropertyTest" ).css( "--color" ), "red", "Modified CSS custom property using object: Assert value is right" ); | ||
|
|
||
| jQuery( "#customPropertyTest" ).css( { "--theme-dark": "purple" } ); | ||
| assert.equal( jQuery( "#customPropertyTest" ).css( "--theme-dark" ), "purple", "Modified CSS custom property with dashed name: Assert value is right" ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A mixed-case custom property test would also be welcome.
|
@mgol Status update: I haven't been able to remove Thanks for the feedback everyone. |
|
What about #3199 (comment) and #3199 (comment)? |
|
@ConnorAtherton Did you look at @markelog's comments? |
|
@ConnorAtherton A friendly ping. :) |
|
@ConnorAtherton We'd like to get it into 3.2.0. If you don't have time to finish please let us know so we'll tweak it & land it ourselves. |
Fixes jquerygh-3144 Closes jquerygh-3199
|
I finished the PR as #3557. |
|
@ConnorAtherton I've finished it up for you in #3557. You'll still be credited as the commit author. Thanks for all the work that went into this PR! |
Fixes jquerygh-3144 Closes jquerygh-3199 Closes jquerygh-3557
Fixes jquerygh-3144 Closes jquerygh-3199 Closes jquerygh-3557
Fixes jquerygh-3144 Closes jquerygh-3199 Closes jquerygh-3557

Summary
Allows users to get and set the value of CSS custom properties on a DOM element through the
.cssmethod.It works exactly like the example in the issue, which I am copying here for reference.
Fixes #3144
Checklist