How can I change a CSS gradient via JavaScript?
11,057
Solution 1
With jQuery it'll be :
$('.gradient').css({'background-image': 'linear-gradient(to top, #2E2E28 0%, #4D4C48 100%)'});
For safari :
$('.gradient').css({'background-image': '-webkit-linear-gradient(top, #2E2E28 0%, #4D4C48 100%)'});
Seems to work cross-browser.
Edit :
I did a small plugin which can help you with the different colors :
;(function($) {
var isSafari = /Safari/.test(navigator.userAgent) && /Apple Computer/.test(navigator.vendor);
var methods = {
init: function (settings) {
settings = $.extend( {
'colors' : ['red', 'blue'],
'direction' : 'top'
}, settings);
return this.each(function(){
if($.isArray(settings.colors) && settings.colors.length >= 2) {
$(this).css({
'background':
methods.gradientToString(settings.colors, settings.direction)
});
} else {
$.error('Please pass an array');
}
});
},
gradientToString: function (colors, direction) {
var nbColors = colors.length;
//If no percent, we need to calculate them
if(colors[0].percent === undefined) {
//Passed only colors as an array we make it an object
if(colors[0].color === undefined) {
var tmp = [];
for(i=0; i < nbColors; i++)
tmp.push({'color':colors[i]});
colors = tmp;
}
var p = 0,
percent = 100 / (nbColors - 1);
//calculate percent
for(i=0; i< nbColors; i++) {
p = i === 0 ? p : (i == nbColors-1 ? 100 : p + percent);
colors[i].percent = p;
}
}
var to = isSafari ? '' : 'to';
//build the string
var gradientString = isSafari ? '-webkit-linear-gradient(' : 'linear-gradient(';
gradientString += to +' '+ direction;
for(i=0; i < nbColors; i++)
gradientString += ', '+ colors[i].color + ' ' + colors[i].percent + '%';
gradientString += ')';
return gradientString;
}
};
$.fn.gradientGenerator = function () {
return methods.init.apply( this, arguments );
};
})(jQuery);
Use it like this for example :
$('.gradient').gradientGenerator({
colors : ['#2E2E28', '#4D4C48']
});
$('.change-color').on('click', function(e) {
e.preventDefault();
$('.gradient').gradientGenerator({
colors : [{color:'#4D4C48',percent:0}, {color:'#282827', percent:30}, {color:'#2E2E28', percent: 100}],
direction : 'left'
});
});
See it working here.
Solution 2
The following function will take two colours as parameters and return the style string, as you've specified it, with the appropriate substrings replaced with the given colours.
You can see this in action here.
var makeGradientStyle = function(){
var gradientString = '\
/* Mozilla Firefox */ \
background-image: -moz-linear-gradient(top, {colour1} 0%, {colour2} 100%);\
/* Opera */ \
background-image: -o-linear-gradient(top, {colour1} 0%, {colour2} 100%);\
/* Webkit (Safari/Chrome 10) */ \
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, {colour1}), color-stop(1, {colour2}));\
/* Webkit (Chrome 11+) */ \
background-image: -webkit-linear-gradient(top, {colour1} 0%, {colour2} 100%);\
/* IE10+ */\
background: -ms-linear-gradient(top, {colour1} 0%,{colour2} 100%);\
/* W3C */\
background: linear-gradient(top, {colour1} 0%,{colour2} 100%);\
';
return function(colour1, colour2){
return gradientString.replace(/\{colour1\}/g, colour1).replace(/\{colour2\}/g, colour2)
}
}();
You can then apply as follows. The disadvantage lies in the fact that you're replacing the entire style string, but you can get round that with
var p = document.getElementById('p');
p.setAttribute('style', p.getAttribute('style') + '; ' + makeGradientStyle('#ff0000', '#0000ff'));
Related videos on Youtube
Author by
The_asMan
Updated on June 14, 2022Comments
-
The_asMan almost 2 years
I have a div with the following gradient applied to it:
/* Mozilla Firefox */ background-image: -moz-linear-gradient(top, #2E2E28 0%, #4D4C48 100%); /* Opera */ background-image: -o-linear-gradient(top, #2E2E28 0%, #4D4C48 100%); /* Webkit (Safari/Chrome 10) */ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #2E2E28), color-stop(1, #4D4C48)); /* Webkit (Chrome 11+) */ background-image: -webkit-linear-gradient(top, #2E2E28 0%, #4D4C48 100%); /* IE10+ */ background: -ms-linear-gradient(top, #2E2E28 0%,#4D4C48 100%); /* W3C */ background: linear-gradient(top, #2E2E28 0%,#4D4C48 100%);
How could I change "#2E2E28" to another number, but still avoid the cross-browser nightmare?
-
The_asMan@Piyuesh Nothing in that example preserves cross-browser functionality
-
-
The_asMan almost 11 yearsAssigning the style as a whole attribute is an interesting idea.
-
The_asMan almost 11 yearsjust tested again jsfiddle.net/soyuka/vnQke does not work in safari on ipad or safari on windows 7 pc
-
soyuka almost 11 yearsYou're right it's working on opera, ff, chrome but not safari, I'm trying to find why.
-
soyuka almost 11 years@The_asMan Now it's working on safari, can you test on iPad ? I didn't tried on IE though.
-
Barney almost 11 yearsYou need to specify different style properties depending on the implementation. I figure you've already got the CSS using in-built logic to handle the different variations, so JS can stick to the stuff it's good at: dynamic modification and DOM manipulation. The other advantage with this method is that you could easily modify the CSS string to cater for old IE via
filter
or some such. -
Barney almost 11 yearsThe key thing being that you don't have to implement alternative logic to determine the appropriate implementation method: CSS takes care of that itself.
-
The_asMan almost 11 yearsbroken in chrome and IE9 not sure need it to work on ie9 but cant test 10 atm
-
soyuka almost 11 yearsPlease test IE10, it won't work with IE9 I've worked on it this morning but it seems a bit useless to me. For IE9 it needs the
filter
attr, only 2 colors compatible and I'm on OS X so it's hard to debug. Maybe you can implement it yourself :). -
The_asMan almost 11 yearsThe specs for our new system haven't been fully set yet but they keep saying "HTML5" so like i was saying probably do not have to support IE9 and under. so can ignore filter. And I don't have an IE10 test environment set up for me yet. I swear you had it working in chrome yesterday
-
Charles Robertson over 6 years@Barney This is a great answer. Thinking outside the box. I have packaged it into a lightweight jQuery plugin, below...