4

I came across a strange issue with jQuery. It seems that when jQuery is used to add multiple css properties with the same name (for cross browser compatibility), each "duplicate" property, is being overwritten and only the last occurrence is being used.

Example, in pure css, I have this:

div.ellipse {
    background-image: radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800);
    background-image: -o-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800);
    background-image: -ms-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800);
    background-image: -moz-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800);
    background-image: -webkit-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800);
}

Fiddle: http://jsfiddle.net/Lzhcdr2f/

The background image property is used multiple times for cross browser compatibility.

Now I try to apply the above css code using jQuery like this:

$('.ellipse').css({ 
    'background-image': 'radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)',
    'background-image': '-o-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)',
    'background-image': '-ms-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)',
    'background-image': '-moz-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)',
    'background-image': '-webkit-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)'
});

Fiddle: http://jsfiddle.net/z9ygxj9j/

The above code will ONLY work in webkit browsers (chrome/safari), because the last line refers to -webkit browser, and jQuery seems to override properties with the same name and only use the last occurrence.

The only way around, seems to be this:

$('.ellipse').css({'background-image': 'radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)'});
$('.ellipse').css({'background-image': '-ms-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)'});
$('.ellipse').css({'background-image': '-moz-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)'});
$('.ellipse').css({'background-image': '-webkit-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)'});
$('.ellipse').css({'background-image': '-o-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)'});

Fiddle: http://jsfiddle.net/cte7ov36/

Is there no way to use the same property multiple times inside the same array?

filype
  • 8,034
  • 10
  • 40
  • 66
Kevin M
  • 1,202
  • 15
  • 30
  • 5
    make a class in css and use .addClass – Mohamed-Yousef May 02 '15 at 06:13
  • 1
    possible duplicate of [Applying inline styles with browser prefixes](http://stackoverflow.com/questions/11072785/applying-inline-styles-with-browser-prefixes) – Patrick May 02 '15 at 06:14
  • @Mohamed-Yousef, I can't, the property values, such as color, are being generated by the user and therefor applied via jquery on the fly. – Kevin M May 02 '15 at 06:15
  • A given style property on a DOM element cannot have multiple values in the way you do it in a stylesheet. Plus an object in Javascript like what you're passing to `.css()` only has one value for a given property anyway. – jfriend00 May 02 '15 at 06:18
  • @Patrick Thanks, but that seems to be something completely different. Not related to my issue. My issue is that jquery overwrites css properties when duplicates are used. – Kevin M May 02 '15 at 06:19
  • @jfriend00 Yeah, it seems javascript is limited in that sense. So I guess the only way around is the way I have explained it in my 3rd example. – Kevin M May 02 '15 at 06:22
  • The link that @Patrick provided seems to be a solution for you. It will test which prefix to use and apply it, allowing you to use a more standard name like `border-radius`. Also, you should clarify in your question that the values of the gradient are _unique/dynamic_. – hungerstar May 02 '15 at 06:24
  • @KevinM As far as I can see, the other question provides the solution in the question itself, not in its answers. – Mr Lister May 02 '15 at 06:30
  • @KevinM my latest edit should provide one option, which would be to use `$.attr('style')` – filype May 02 '15 at 06:40

4 Answers4

10

The easiest way to maintain this code would be to store your css in a class and use in your elements. Style definition should be separate to your code.

if you really want to do this in jQuery you can use the attr style

var style = [
    'background-image: radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)',
    'background-image: -o-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)',
    'background-image: -ms-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)',
    'background-image: -moz-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)',
    'background-image: -webkit-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)'
].join(';');

$('.ellipse').attr('style', style);

http://jsfiddle.net/z9ygxj9j/2/

filype
  • 8,034
  • 10
  • 40
  • 66
1

This is possible by other way

[js fiddle][1]:http://jsfiddle.net/cte7ov36/2/

$('.ellipse').attr('style','background-image: radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800);background-image: -ms-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800);background-image: -moz-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800);background-image: -webkit-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800);background-image: -o-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)');
Super User
  • 9,448
  • 3
  • 31
  • 47
1

Note,

calling .css()

ellipse
.css("background-image", "-[vendorPrefix]-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)");

should not affect non [vendorPrefix] browser display , rendering ; save for possibly opera, which not certain if still utilizes both -o- and -webkit- ?

This approach checks for a property of element.style ; replaces given text values within style element text with vendor prefixed value text.

Try

var ellipse = $('.ellipse')
, style = $("style")
, prefixes = {
    "MozAnimation": "-moz-",
    "webkitAnimation": "-webkit-",
    "msAnimation": "-ms-",
    "oAnimation": "-o-"
  };
// should not affect non `-moz-` browser 
ellipse
.css("background-image", "-moz-radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800)");

$.each(prefixes, function(key, val) {
  if (key in ellipse[0].style) {
    $("style").text(function(i, text) {
      return text.replace(/(radial-gradient)/g, val + "$1")
    })
  }
});

console.log(style.text(), ellipse.css("backgroundImage"));
.demo-wrapper div {
  width: 910px;
  height: 250px;
  padding: 10px;
  margin: 25px auto;
  border: 5px solid #fff;
}
.ellipse {
  background-image: radial-gradient(center bottom, ellipse cover, #ffeda3, #ffc800);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="demo-wrapper">
  <div class="ellipse">
    <h3>Elliptical Gradient</h3>
    Lorem Ipsum</div>
</div>

jsfiddle http://jsfiddle.net/cte7ov36/3/

guest271314
  • 1
  • 15
  • 104
  • 177
  • Thanks. That's a great way to do it site wide. Also, thanks for the hint about -o. I wasn't aware that Opera switched over to webkit in 2013. Seems since opera 15, it only accepts -webkit prefix. – Kevin M May 03 '15 at 08:45
0

As you said, you try to appear styles generated by the user with some application. We don't know what is exact format of the styles you get from that program element so it is hard to create good answer.

The answer in the comment by Patrick seems to be useful (just instead of transform use radial-gradient). If you gets all styles together like a block of text then use Filipes answer. Also you can detect browser firstly and that apply only that styles that you need (there is example how you can do that).

Community
  • 1
  • 1
jazzgot
  • 368
  • 1
  • 2
  • 16