Vendor prefixing with inline styles - javascript

I'm in a situation where I need to dynamically animate the position of an element with jQuery. I have some external css that takes care of all things css, then my script adds a transform inline style.
html:
<div></div>
css:
div {
width: 100px;
height: 100px;
background: pink;
transition: all 1s ease;
}
js:
$(function() {
setTimeout(function() {
$('div').css({
'-webkit-transform' : 'translateY(100%)',
'-ms-transform' : 'translateY(100%)',
'transform' : 'translateY(100%)',
});
}, 1000);
});
My question is why are all browsers I am testing (Safari 11.0.2, Firefox 56.0, Chrome 63.0.3239.84) ignoring the vendor-prefixing and returning the following?
<div style="transform: translateY(100%);"></div>
I'm obviously looking to support as many browsers as possible...
Fiddle here if seeing what the code does helps.

No browser has required a prefix for transform for many years. Once unprefixed transform has shipped, a browser simply implements its prefixed property as an alias of the unprefixed property, which means that the prefixed and unprefixed declarations will override one another in the cascade depending on the order of declarations. Furthermore, since they are aliases, they'll still show up as unprefixed even if you remove the explicit unprefixed declaration.
This is just browsers' way of telling you not to worry about the prefixes in the newer versions that don't need them. They are intended for older versions that don't yet support the unprefixed properties. For example, the only version of Internet Explorer that requires -ms-transform is 9. Internet Explorer 10, which doesn't need the prefix (for transforms and many other features), came out in 2012. Note also that some browsers, like Firefox, are known to drop support for really old prefixed properties altogether after keeping them aliased for a while — again, not something you have to worry about since you always make sure to include unprefixed declarations (which not everyone does).

Related

Why does .css('fontSize') produce different results in Edge?

Consider this code (also in a fiddle):
document.getElementById("span").innerHTML += $('#input').css('fontSize');
span input {
font-size: inherit;
}
input {
font-size: 15px;
}
<span id="span" style="font-size: 30px;">
<input id="input"/>
</span>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
In Chrome and Firefox, the .css('fontSize') will return 30px, in Edge and IE it's 15px. Why does it do that? The DOM Explorer in Edge even shows the 15px in strikethrough, and therefore should take the inherited 30px as the fontSize:
And the input is rendered with a 30px font, so IE/Edge is picking it up for rendering purposes.
Update: The bug below is now fixed; FremyCompany says he/she is a program manager from the Edge team and the fix will reach customers in early 2017.
It looks very much like an IE and Edge bug. Not having found it, I reported it.
Here's an update to the snippet that sees what IE/Edge is telling jQuery via getComputedStyle or currentStyle:
var input = $("#input");
console.log("jQuery: " + input.css('fontSize'));
if (window.getComputedStyle) {
console.log("getComputedStyle: " + getComputedStyle(input[0]).fontSize);
}
if (input[0].currentStyle) {
console.log("currentStyle: " + input[0].currentStyle.fontSize);
}
span input {
font-size: inherit;
}
input {
font-size: 15px;
}
<span id="span" style="font-size: 30px;">
<input id="input"/>
<span id="size"></span>
</span>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
For me, IE11 returns 15px from both getComputedStyle and the Microsoft-specific currentStyle property (it's reassuring that they do at least say the same thing):
So it's not a jQuery bug, it's a Microsoft bug when reporting the size via JavaScript (looks like when inherit is the governing rule), even though it's rendering it correctly.
I tried to find a way to make this a grey area, but couldn't think of anything. For instance, according to the spec, having an input inside a span is entirely valid.
Before I get to the real answer I'd like to dig a little into details.
What is this piece of code doing?
.css();
In the jQuery Docs they tell us:
Get the value of a computed style property for the first element in
the set of matched elements or set one or more CSS properties for
every matched element.
Furthermore:
The .css() method is a convenient way to get a computed style property
from the first matched element, especially in light of the different
ways browsers access most of those properties (...)
So what does computed mean?
MDN Docs:
the computed value of a CSS property is computed from the specified
value by:
Handling the special values inherit and initial, and
Doing the computation needed to reach the value described in the "Computed value" line in the property's summary
Ok, now that part is clear too. Let's get to the real answer:
According to Specifics on CSS Specificity there are css-rules with more 'weight' than others have on an HTML element.
Here is the actual order:
Style Attribute
ID
Class, Pseudo Class Attributes
Element
According to that rules your input should've taken the inherited 30px from the Style attribute.
So what is happening in IE11/Edge?
IE11 and Edge are both computing the CSS Rules wrong. If you change your CSS into only this:
span input {
font-size: inherit;
}
It is starting to work. With the information gathered I am assuming that the JavaScript - Engine of both is computing the real CSS value instead of following the CSS rules order.
I've tried to either change the ID and putting a class on the input but still no luck.
I can remember that IE11 and Edge had some problems with inherited CSS and pseudo classes, maybe it is related to that?
Regards,
Megajin

How can this CSS card flip effect fall back gracefully when CSS3 support is lacking?

I'm using the library FlipClock.js to build an analog-style clock that uses a version of the CSS "card flip effect." Unfortunately, only after building out my project did I notice a long-standing bug affecting Internet Explorer 9 and below:
https://github.com/objectivehtml/FlipClock/issues/7
In IE9 and below, the clock time lags by one second (i.e., in the first second of animation, nothing visible changes), and the digits in the clock are also offset by a value of 1. My expectation is not for the CSS flip animation to work, but for the digits to change instantly as they currently do, only be correct.
I've been troubleshooting for a while but have yet to find a solution or even pinpoint the problem. I have a hunch that this isn't a script-related bug; I suspect that the digits are changing correctly in the HTML (hard to verify with IE's developer tools), but that they're just not showing as intended due to one or more CSS rules that were written not considering IE9's poor CSS3 support. I'm kind of expecting (or at least hoping) to stumble upon a CSS property or two that just fixes it.
The library is based on a proof-of-concept, which exhibits the same problem:
http://codepen.io/ademilter/pen/czIGo
I'm troubleshooting there to keep it simple, and if I find a fix, will submit a pull request to the FlipClock.js library.
I would greatly appreciate any help!
After removing the CSS animations and shadows, changing the z-index of li.before might do the trick (see http://codepen.io/cbuckley/pen/rysja):
body.play ul li.before {
z-index: 1; /* was previously 3 */
}
So you could use z-index: 1 by default, then feature-detect for CSS animations in the JavaScript and add a body class (say body.supports-animation). Then the relevant CSS might look like:
body.play ul li.before {
z-index: 1;
}
body.play.supports-animation ul li.before {
z-index: 3;
}
/* Prefix animation/background declarations with body.supports-animation too */
Caveat: I haven't tried this with FlipClock, nor have I actually tested on a browser without animation support, but I hope it gives one possible option :-)
Just changing the z-index will fix the problem for IE8 and IE9 but will break the transition for all modern browsers.
To Target specifically I8 or IE9 you can use this:
On your JS file add:
var doc = document.documentElement;
doc.setAttribute('data-useragent', navigator.userAgent);
then on your css you can detect IE8 and IE9 with this code (flipclock.css line 160):
/* PLAY */
.flip-clock-wrapper ul.play li.flip-clock-before {
z-index: 3;/*Original */
}
/*ie8 and ie9 fixes*/
html[data-useragent*='MSIE 8.0'] .flip-clock-wrapper ul.play li.flip-clock-before {
z-index: 1;
}
html[data-useragent*='MSIE 9.0'] .flip-clock-wrapper ul.play li.flip-clock-before {
z-index: 1;
}
That fixed the problem for me!

Detecting CSS capabilities with Javascript

Is it possible to detect CSS support by using Javascript?
For example, is it possible to detect if the browser supports attribute selectors like this?
input[type='text'] { }
Modernizr is designed to detect browser features and may well be able to help in this instance.
http://www.modernizr.com/
This is a bit speculative as I haven't tested it out, but I believe it would be possible via JS to add a style element followed by an element that it has an effect on, and then test the values:
Speculative untested code, may or may not work (jQuery used for brevity):
$('<style type="text/css" id="foo">input[type="text"]{ width: 10px; }</style>').appendTo('head');
$('<input type="text" id="bar">').appendTo('body');
if ($('#bar').width() == 10)
{
//attr selector supported
}
$('#foo, #bar').remove();
document.querySelectorAll("input[type='text']")
But that fails for older browsers, naturally.
Other than that, you could just use the style property to check if a certain CSS property has been applied or not.
input[type='text'] {
background-repeat: no-repeat; /* or any other irrelevant, non-default value */
}
and
if (myInputElem.style.backgroundRepeat == "no-repeat") {
// selector is supported
}

If Browser, Use Javascript?

I have a script that detects what browser (and version) someone is using, and I'd like to set it up so that for certain browsers, a div class gets an animation on hover. I'd like to do this using jQuery, but I'm open to whatever.
My idea for the JavaScript is this...
if (browser == IE || browser < Firefox 4) {
// somehow animate a div class on hover (could be id-based too)
} else {
// do nothing
}
The CSS I have set up for this is something like this
.item {
height: 100px;
width: 100px;
/* css3 */
transition: height .5s, width .5s;
-moz-transition: height .5s, width .5s;
-webkit-transition: height .5s, width .5s;
}
.item:hover {
height: 200px;
width: 200px;
}
And then the HTML is (obviously)
<div class="item" id="item">
<p>Content here</p>
</div><!-- end item -->
The purpose is a CSS3 fix for older browsers. Transitions are, in my opinion, one of the best things about CSS3, and it annoys the hell out of me that IE9 doesn't include support for them.
Instead of this, how about using something like the Modernizr library?
http://www.modernizr.com/
Modernizr adds classes to the element which allow you to target specific browser functionality in your stylesheet. You don't actually need to write any Javascript to use it.
You can then do stuff like this:
.multiplebgs div p {
/* properties for browsers that
support multiple backgrounds */
}
.no-multiplebgs div p {
/* optional fallback properties
for browsers that don't */
}
You're going down a very dangerous path here using browser sniffing like that.
What you should be trying to do instead is use feature detection. There are libraries out there like the fantastic Modernizr which can do this for you.
Use $.support to check if the browser supports it and not even have to mess with version detecting. This helps future proof your code and more accurately models what you really want to do.
In fact, there's already a jQuery plugin to do this specifically. :D
Browser sniffing is not the best way to write JS-code.
If you prefer jQuery, here is jQuery.browser object
Some examples:
if ($.browser.webkit) {
alert( "this is webkit!" );
}
var ua = $.browser;
if ( ua.mozilla && ua.version.slice(0,3) == "1.9" ) {
alert( "Do stuff for firefox 3" );
}
if ( $.browser.msie ) {
$("#div ul li").css( "display","inline" );
} else {
$("#div ul li").css( "display","inline-table" );
}
You could do something like this:
<![if (IE 6)|(IE 7)|(IE 8)]-->
<link type="text/css" rel="stylesheet" href="nocss3.css" />
<script type="text/javascript" src="nocss3.js"></script>
<![endif]-->
You can use the library Modernizer (http://www.modernizr.com) which detects and fixes support of various HTML 5 and CSS3 features on different browsers.
Here's what they have in their documentation about CSS3 transitions:
http://www.modernizr.com/docs/#csstransitions
CSS Transitions are an incredibly
useful new part of CSS3. Using them,
you can let the browser animate—or
rather, transition—from one state to
the other. You only have to specify a
start and end and the browser takes
care of the rest.
In Modernizr we test for CSS
Transitions using the transition
property with all vendor prefixes.
Transitions can typically be used
without using Modernizr's specific CSS
class or JavaScript property, but for
those occasions you want parts of your
site to look and/or behave differently
they are available. A good example use
case is to build Modernizr into an
animation engine, which uses native
CSS Transitions in the browsers that
have it, and relies on JavaScript for
the animation in browsers that don't.
Sample Usage:
a {
color: #090;
-webkit-transition: color .2s ease-out;
}
a:focus,
a:hover {
color: #9f9;
}
You might look in to this tutorial https://developer.mozilla.org/en/Browser_Detection_and_Cross_Browser_Support

Detect :first-child support

How to detect, using JavaScript, if the browser supports the CSS :first-child selector?
You could just use that :first-child rule to set some specific value, and then get the computed style in Javascript to see if the :first-child rule is applied, e.g.
<style>
#foo { width: 200px; }
#foo:first-child { width: 400px; }
</style>
<span><span id="foo"></span></span>
<script>
if ($('#foo').width() < 400)
alert('first-child not supported.');
</script>
(This is not tested. I have no IE 6.)
I don't think there is a jQuery function to find out support for this. I expect if it does exist, it is going to be quite complicated. Are you really sure you need this? Care to share why?
If you can use jQuery anyway, why not add a jQuery statement to assign the class/property/whatever to the desired element, instead of relying on CSS?
As a "manual" answer, looking at the quirksmode.org compatibility table, the selector is fully supported in all modern browsers except the IE family which seems to have problems even in IE8.

Categories

Resources