07 Jun 2012

CSS3 Safari vs. Chrome (Mac OS X)

Currently i'm working on ( well actually i'm trying to work on ) a web-game. It's suppose to be a turn-based mltiplayer game like `Dice Wars` ( google it! ) built on HTML5, CSS3, JavaScript etc. technologies...


For now it is:
Server: PHP
Client: HTML, CSS, JavaScript ( Ajax )

Currently I'm working on:
Mac OS X 10.7 Lion ( mostly )
Safari Version 5.1.7 (7534.57.2)
Chrome Version 19.0.1084.54

And I want to write about some difficulties and differences that I found.


I've chosen to work with these browsers ( Safari and Chrome ) because I have already done some work ( webs, web apps ) with them and I think that WebKit Project has bright future. I know that these browsers are going separate ways in implementing JavaScript [ Chrome has V8 JS engine and Safari uses SquirrelFish (JavaScriptCore) ]. But I thought they implement other things as CSS3 same way, apparently I was wrong. I'm just saying... not judging, because I know specifications are not ( and won't be anytime soon ) finished. I just want to point out these things...


I was doing some 3d transform with CSS3 and everything was fine... until I tried it with Chrome. It looked different, so I made a test cases:


CSSHTML

	body {
		-webkit-perspective: 500px;
	}
	#parent {
		background-color: blue;
		-webkit-transform-style: preserve-3d;
		position: absolute;
		left: 100px;
		top: 100px;
		width: 100px;
		height: 100px;
	}
	#child {
		background-color: red;
		-webkit-transform-style: preserve-3d;
		position: absolute;
		left: 80px;
		top: 30px;
		width: 40px;
		height: 40px;
		-webkit-transform: rotateX(45deg);
	}
	

	<body>
	<div id="parent">
		<div id="child"></div>
	</div>
	</body>
	

Safari Version 5.1.7 (7534.57.2) - Mac OS XChrome Version 19.0.1084.54 - Mac OS X

Well... See the difference? In Safari half of rotated #child element is hidden behind #parent element ( actually it is quarter, not half, but you see my point ). And this is the way I think it should be ( I like it this way better ), but I didn't read specification so I don't know which one is correct. z-index does not make difference here.


But now I read it(specification, just part of it), and if I understand it right then Safari has it correctly.

It says:

Elements in the same 3D rendering context may intersect with each other. User agents must render intersection by subdividing the planes of intersecting elements as described by Newell's algorithm. Untransformed elements in a 3D rendering context render on the Z=0 plane, yet may still intersect with transformed elements.

But are they in same 3d rendering context? Since it is parent/child ?




Let's change #child's property:

-webkit-transform: rotateX(45deg) translateZ(-1px);


Result is:


Safari Version 5.1.7 (7534.57.2) - Mac OS XChrome Version 19.0.1084.54 - Mac OS X

We moved #child element -1px on Z-axis and in Chrome it's now whole behind #parent. I've also tried to change z-index of #child and #parent, but it doesn't make any change. It is probably because one element (#child) is child of other (#parent).





Let's change hierarchy of elements, so they'll be equal (same parent, not parent/child)

CSSHTML

	body {
		-webkit-perspective: 500px;
	}
	#blue {
		background-color: blue;
		-webkit-transform-style: preserve-3d;
		position: absolute;
		left: 100px;
		top: 100px;
		width: 100px;
		height: 100px;
		-webkit-transform: translateZ(0px);
	/*	z-index: 1; */	
	}
	#red {
		background-color: red;
		-webkit-transform-style: preserve-3d;
		position: absolute;
		left: 180px;
		top: 130px;
		width: 40px;
		height: 40px;
		-webkit-transform: rotateX(45deg) translateZ(0px);
	/*	z-index: 0; */	
	}
	
	<body>
	<div id="blue"></div>
	<div id="red"></div>
	</body>
	

Safari Version 5.1.7 (7534.57.2) - Mac OS XChrome Version 19.0.1084.54 - Mac OS X

Yes, it's same as it was in first test-case. ( that's why I used same images - I'm being "green" so you don't have to download same pictures twice :-) )


Notice commented lines in CSS. There is z-index, 1 for #blue and 0 for #red, uncomment it and see the result:


Safari Version 5.1.7 (7534.57.2) - Mac OS XChrome Version 19.0.1084.54 - Mac OS X

As you can see it looks same at Safari but this time in Chrome z-index does make difference (unlike in parent/child hierarchy).





Let's now "play" with translating on Z axis and keep z-index-es uncommented. Results are in my opinion interesting.



CSSHTML

	body {
		-webkit-perspective: 500px;
	}
	#blue {
		background-color: blue;
		-webkit-transform-style: preserve-3d;
		position: absolute;
		left: 100px;
		top: 100px;
		width: 100px;
		height: 100px;
		-webkit-transform: translateZ(-100px);
		z-index: 1; 	
	}
	#red {
		background-color: red;
		-webkit-transform-style: preserve-3d;
		position: absolute;
		left: 180px;
		top: 130px;
		width: 40px;
		height: 40px;
		-webkit-transform: rotateX(45deg) translateZ(0px);
		z-index: 0; 	
	}
	

	<body>
	<div id="blue"></div>
	<div id="red"></div>
	</body>
	

We just added translateZ(-100px) to #blue element.


Safari Version 5.1.7 (7534.57.2) - Mac OS XChrome Version 19.0.1084.54 - Mac OS X

In this case, no matter what we do with property -webkit-transform: translateZ(); in Chrome will always #blue element be in front of #red, because of z-index. In Safari it does count, you may get #blue in front of #red or vice versa with chaging value of translateZ.


But apparently I'm an idiot, I just found out ( while writing this article ) that when you add to body property -webkit-transform-style: preserve-3d; then it works in Chrome same as in Safari ( except intersecting, thats still seems to sucks in Chrome )


Specification says:

Within a 3D rendering context, the rendering order of non-intersecting elements is based on their position on the Z axis after the application of the accumulated transform. Elements at the same Z position render in stacking context order.


So it seems to be correct, I guess... I'm really confused now... The lesson I will(hopefully) take from this is to do more testing and more reading before writing.




Also I was testing it on my old computer with Windows XP... In Safari( 5.1.7 (7534.57.2) ) it was same as in Safari on Mac OS X. On the other hand in Chrome it didn't work at all ( 3d transforms ). So I tried to find out why... Apparently when you have old graphics card (and/or old drivers) then Chrome disables it for better performance. You can try to enable it in Chrome's about:flags (chrome://flags) page as it says for example here. In my case it didn't work, but it may in yours.


Conclusion:
When I started writing this article I thought there were more problems, but as I was writing it, testing it and reading some other articles and specifications I found out that I was mistaken. Only these problems seems to be legit:
- intersecting in Chrome
- 3d transforms in Chrome on older devices ( disabled, or not working ), while Safari seems to run it allright