4

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?

7
  • doesn't this work for you ?stackoverflow.com/questions/11943322/… Commented Apr 25, 2013 at 15:39
  • if you're happy using jQuery, it normalises the styles so you don't need to include all the prefixes. Commented Apr 25, 2013 at 15:40
  • 1
    @Piyuesh Nothing in that example preserves cross-browser functionality Commented Apr 25, 2013 at 15:46
  • @Spudley Jquery is fine. could you give an example. Commented Apr 25, 2013 at 15:47
  • @The_asMan one answer from that question does, but jQuery has evolved since it was written so that the vendor prefix properties are no longer needed and it handles it transparently. This was changed for jQuery 1.8 - see #10679 Commented Apr 25, 2013 at 15:52

3 Answers 3

6

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'));
Sign up to request clarification or add additional context in comments.

4 Comments

Assigning the style as a whole attribute is an interesting idea.
You 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.
The key thing being that you don't have to implement alternative logic to determine the appropriate implementation method: CSS takes care of that itself.
@Barney This is a great answer. Thinking outside the box. I have packaged it into a lightweight jQuery plugin, below...
5

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%)'});

See here for a live example.

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.

6 Comments

just tested again jsfiddle.net/soyuka/vnQke does not work in safari on ipad or safari on windows 7 pc
You're right it's working on opera, ff, chrome but not safari, I'm trying to find why.
@The_asMan Now it's working on safari, can you test on iPad ? I didn't tried on IE though.
broken in chrome and IE9 not sure need it to work on ie9 but cant test 10 atm
Please 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 :).
|
0

Building on Barney's excellent answer, here is a small jQuery plug-in:

(function($) { 

  $.fn.cssGradient = function(options) {

    // support multiple elements

    if(this.length > 1){
      this.each(function(){
        $(this).cssGradient(options);
      });
      return this;
    }

    // private variables

    var that = this;

    var metaData = {};
    metaData['version'] = "1.0.0";

    // settings

    // Extend our default options with those provided.
    // Note that the first argument to extend is an empty
    // object – this is to keep from overriding our "defaults" object.

    var defaultOptions = {
          background:'',
          color1:'',
          color2:''
        }

    var settings = $.extend({},defaultOptions,options);

    // private methods

    var init = function() {
      start();
      return that;
    }

    var start = function(){
      var element = jQuery(that);
      var attr = element.attr('style');
      var style = "";
      if (typeof attr !== typeof undefined && attr !== false) {
        style = element.attr('style') + makeGradientStyle(settings.background,settings.color1,settings.color2);
      }
      else{
        style = makeGradientStyle(settings.background,settings.color1,settings.color2);
      }
      element.attr('style',style);
    }

    var makeGradientStyle = function(background,color1,color2){
      var gradientString = 'background:{background};background-image:-moz-linear-gradient(top,{color1} 0%,{color2} 100%);background-image:-o-linear-gradient(top,{color1} 0%,{color2} 100%);background-image:-webkit-linear-gradient(top,{color1} 0%,{color2} 100%);background-image:-ms-linear-gradient(top,{color1} 0%,{color2} 100%);background-image:linear-gradient(to bottom,{color1} 0%,{color2} 100%);';
      return gradientString.replace(/\{background\}/g,background).replace(/\{color1\}/g,color1).replace(/\{color2\}/g,color2);
    }

    // public methods

    this.version = function() {
      console.log('cssGradient plugin version: ',metaData['version']);
    };

    return init();

  }

})(jQuery);

And to implement:

var cssGradient = jQuery('.foo').cssGradient({background:'#fff',color1:'#fff',color2:'#ff0000'});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.