
Object manipulation with CSS3
Prior to the advent of CSS3, web developers used a laundry list of content manipulation, asset preparation, and asset presentation techniques in order to get their web page layout the way they wanted in every browser. Most of these techniques would be considered "hacks" as they would pretty much be a work around to enable the browser to do something it normally wouldn't. Features such as rounded corners, drop shadows, and transforms were all absent from a web developer's arsenal and the process of getting things the way you want could get mind numbing. Understandably, the excitement level surrounding CSS3 for all web developers is very high as it enables developers to perform more content manipulation techniques then ever before without the need for prior preparation or special browser hacks. Although the list of available properties in CSS3 is massive, let's cover some of the newest and most exciting of the lot.
box-shadow
It's true that some designers and developers say drop shadows are a part of the past, but the usage of shadowing HTML elements is still a popular design choice for many. In the past, web developers needed to perform tricks such as stretching small gradient images or creating the shadow directly into their background image to achieve this effect in their HTML documents. CSS3 has solved this issue by creating the box-shadow
property to allow for drop shadow like effects on your HTML elements.
To remind us how this effect was accomplished in ActionScript 3, let's review this code snippet:
var dropShadow:DropShadowFilter = new DropShadowFilter();
dropShadow.distance = 0;
dropShadow.angle = 45;
dropShadow.color = 0x333333;
dropShadow.alpha = 1;
dropShadow.blurX = 10;
dropShadow.blurY = 10;
dropShadow.strength = 1;
dropShadow.quality = 15;
dropShadow.inner = false;
var mySprite:Sprite = new Sprite();
mySprite.filters = new Array(dropShadow);
As mentioned before, the new box-shadow
property in CSS3 allows you to append these shadowing effects with relative ease and many of the same configuration properties:
.box-shadow-example { box-shadow: 3px 3px 5px 6px #000000; }
Despite the lack of property names on each of the values applied to this style, you can see that many of the value types coincide with what was appended to the drop shadow we created in ActionScript 3.
This box-shadow
property is assigned to the.box-shadow-example
class and therefore will be applied to any element that has that classname appended to it. By creating a div
element with the box-shadow-example
class, we can alter our content to look something like the following:
<div class="box-shadow-example">CSS3 box-shadow Property</div>

As straightforward as this CSS property is to add to your project, it declares a lot of values all in a single line. Let's review each of these values in order that we can understand them better for future usage. To simplify the identification of each of the variables in the property, each of these have been updated to be different:
box-shadow: 1px 2px 3px 4px #000000;
These variables are explained as follows:
- The initial value (
1px
) is the shadow's horizontal offset or if the shadow is going to the left or to the right. A positive value would place the shadow on the right of the element, a negative offset will put the shadow on the left. - The second value (
2px
) is the vertical offset, and just like the horizontal offset value, a negative number would generate a shadow going up and a positive value would generate the shadow going down. - The third value (
3px
) is the blur radius that controls how much blur effect will be added to the shadow. Declaring a value, for example,0
would create no blur and display a very sharp looking shadow. Negative values placed into the blur radius will be ignored and render no different then using 0. - The fourth value (
4px
) and last of the numerical properties is the spread radius. The spread radius controls how far the drop shadow blur will spread past the initial shadow size declaration. If a value0
is used, the shadow will display with the default blur radius set and apply no changes. Positive numerical values will yield a shadow that blurs further and negative value will make the shadow blur smaller. - The final value is the hexadecimal color value, which states the color that the shadow will be in.
Alternatively, you could use box-shadow
to apply the shadow effect to the interior of your element rather then the exterior. With ActionScript 3, this was accomplished by appending dropShadow.inner = true;
to the list of parameters in your DropShadowFiler
object. The CSS3 syntax to apply box-shadow
properties in this manner is very similar as all that is required is the addition of the inset
keyword. Consider the following code snippet, for example:
.box-shadow-example { box-shadow: 3px 3px 5px 6px #666666 inset; }
This would produce a shadow that would look like the following screenshot:

Tip
Included in the code examples for this chapter is a box-shadow tool that will allow you to better understand the affect each of the properties will have.
text-shadow
Just like the box-shadow
property, text-shadow
lives up to its name by creating the same drop-shadowing effect, specifically for text:
text-shadow: 2px 2px 6px #ff0000;
Like box-shadow
, the initial two values for text-shadow
are the horizontal and vertical offsets for the shadow placement. The third value, which is optional is the blur size and the fourth value is the hexadecimal color:

border-radius
Just like element or text shadowing, adding rounded corners to your elements prior to CSS3 was a chore. Developers would usually append separate images or use other object manipulation techniques to achieve this effect on the typically square or rectangle shaped elements. With the addition of the border-radius
setting in CSS3, developers can easily and dynamically set element corner roundness with only a couple of line of CSS all without the usage of vector 9 slicing like in Flash.
Since HTML elements have four corners, when appending the border-radius
styling, we can either target each corner individually, or all the corners at once. In order to easily append a border radius setting to all the corners at once, we would create our CSS properties as follows:
#example { background-color:#ff0000; // Red background width: 200px; height: 200px; border-radius: 10px; }
The preceding CSS not only appends a 10px border radius to all of the corners of the #example
element, by using all the properties, which the modern browsers use, we can be assured that the effect will be visible to all users attempting to view this content:

As mentioned above, each of the individual corners of the element can be targeted to only append the radius to a specific part of the element:
#example { border-top-left-radius: 0px; // This is doing nothing border-top-right-radius: 5px; border-bottom-right-radius: 20px; border-bottom-left-radius: 100px; }
The preceding CSS now removes our #example
element's left border radius by setting it to 0px
and sets a specific radius to each of the other corners. It's worth noting here that setting a border radius equal to 0
is no different than leaving that property completely out of the CSS styles:

Fonts
Dealing with customized fonts in Flash has had its ups and downs over the years. Any Flash developer who has needed to incorporate and use customized fonts in their Flash applications probably knows the pain that comes with choosing a font embedding method as well as making sure it works properly for users who don't have the font installed on their computer viewing the Flash application.
CSS3 font embedding has implemented a "no fuss" way to include custom fonts into your HTML5 documents with the addition of the @font-face
declaration:
@font-face { font-family: ClickerScript; src: url('ClickerScript-Regular.ttf'), url('ClickerScript-Regular .otf'), url('ClickerScript-Regular .eot'); }
CSS can now directly reference your TTF, OTF, or EOT font which can be placed on your web server for accessibility. With the font source declared in our CSS document and a unique font-family
identification applied to it, we can start using it on specific elements by using the font-family
property:
#example { font-family: ClickerScript; }
Since we declared a specific font family name in the @font-face
property, we can use that custom name on pretty much any element henceforth. Custom fonts can be applied to almost anything that contains text in your HTML document. Form elements such as button labels and text inputs also can be styled to used your custom fonts. You can even remake assets such as website logos in pure HTML and CSS with the same custom fonts used in the original asset creation.
Acceptable font formats
Like many of the other embedding methods for assets online, fonts needs to be converted into multiple formats to enable all common modern browsers to display them properly. Almost all of the available browsers will be able to handle the common True Type Fonts (.ttf
file types) or Open Type Fonts (.otf
file types), so embedding one of those two formats will be all that is needed. Unfortunately Internet Explorer 9 does not have support built in for either of those two popular formats and requires fonts to be saved in the EOT file format.
External font libraries
Many great services have appeared online in the last couple of years allowing web developers to painlessly prepare and embed fonts into their websites. Google's Web Fonts archive available at http://www.google.com/webfonts hosts a large set of open source fonts which can be added to your project without the need to worry about licensing or payment issues. Simply add a couple of extras lines of code into your HTML document and you are ready to go.
Another great site that is worth checking out is Font Squirrel, which can be found at http://www.fontsquirrel.com. Like Google Web Fonts, Font Squirrel hosts a large archive of web-ready fonts with the copy-and-paste-ready code snippets to add them to your document. Another great feature on this site is the @font-face
generator which give you the ability to convert your preexisting fonts into all the web compatible formats.
Before getting carried away and converting all your favorite fonts into web ready formats and integrating them into your work, it is worth noting the End User License Agreement or EULA that came with the font to begin with. Converting many available fonts for use on the web will break license agreements and could cause legal issues for you down the road.
Opacity
More commonly known as "alpha" to the Flash developer, setting the opacity of an element not only allows you to change the look and feel of your designs, but allows you to add features like content that fades in and out. As simple as this concept seems, it is relatively new to the available list of CSS properties available to web developers. Setting the opacity of an element is extremely easy and looks something like the following:
#example { opacity: 0.5; }
As you can see from the preceding example, like ActionScript 3, the opacity value is a numerical value between 0 and 1. The preceding example would display a element at 50 percent transparency. The opacity property in CSS3 is now supported in all the major browsers, so there is no need to worry about using alternative property syntax when declaring it.
RGB and RGBA coloring
When dealing with color values in CSS, many developers would typically use hexadecimal values, which would resemble something like #000000
to declare the usage of the color black. Colors can also be implemented in their RGB representation in CSS by utilizing the rgb()
or rgba()
calls in place of the hexadecimal value. As you can see by the method name, the rgba
color lookup in CSS also requires a forth parameter which declares the colors alpha transparency or opacity amount. Using RGBA in CSS3 rather than hexadecimal colors can be beneficial for a couple of reasons. Consider you have just created a div
element which will be displayed on top of existing content within your web page layout.
If you ever wanted to set a background color to the div
as a specific color but wish for only that background to be semi transparent and not the interior content, the RGBA color declaration now allows you to do this easily as you can set the colors transparency:
#example { // Background opacity background: rgba(0, 0, 0, 0.5); // Black 50% opacity // Box-shadow box-shadow: 1px 2px 3px 4px rgba(255, 255, 255, 0.8); // White 80% opacity
// Text opacity color: rgba(255, 255, 255, 1); // White no transparency color: rgb(255, 255, 255); // This would accomplish the same styling // Text Drop Shadows (with opacity) text-shadow: 5px 5px 3px rgba(135, 100, 240, 0.5); }
As you can see in the preceding example, you can freely use RGB and RGBA values rather than hexadecimal anywhere color values are required in CSS syntax.
Element transforms
Personally, I find CSS3 transforms to be one of the most exciting and fun new features in CSS. Transforming assets in the Flash IDE as well as with ActionScript has always been easily accessible and easy to implement. Transforming HTML elements is a relatively new feature to CSS and is still gaining full support by all the modern browsers.
Transforming an element allows you to manipulate its shape and size by opening up a ton of possibilities for animations and visual effects to assets without the need to prepare the source before hand. When we refer to "transforming an element", we are actually describing a number of properties that can be applied to the transformation to give it different characteristics. If you have transformed objects in Flash or possibly in Photoshop before, these properties may be familiar to you.
Translate
As a Flash developer used to primarily dealing with X and Y coordinates when positioning elements, the CSS3 Translate Transform property is a very handy way of placing elements and it works on the same principal. The translate
property takes two parameters which are the X and the Y values to translate, or effectively move the element:
transform:translate(-25px, -25px);
Unfortunately, to get your transforms to work in all browsers, you will need to target each of them when you append transform styles. Therefore, the standard transform style and property would now look something like this:
transform:translate(-25px, -25px); -ms-transform:translate(-25px, -25px); /* IE 9 */ -moz-transform:translate(-25px, -25px); /* Firefox */ -webkit-transform:translate(-25px, -25px); /* Safari and Chrome */ -o-transform:translate(-25px, -25px); /* Opera */
Rotate
Rotation is pretty self-explanatory and extremely easy to implement. The rotate
properties take a single parameter to specify the amount of rotation, in degrees, to apply to the specific element:
transform:rotate(45deg); -ms-transform:rotate(45deg); /* IE 9 */ -moz-transform:rotate(45deg); /* Firefox */ -webkit-transform:rotate(45deg); /* Safari and Chrome */ -o-transform:rotate(45deg); /* Opera */
It is worth noting that regardless of the fact that the supplied value is always intended to be a value in degrees, the value must always have deg appended for the value to be properly recognized.
Scale
Just like rotate
transforms, scaling is pretty straightforward. The scale
property requires two parameters, which declare the scale amount for both X and Y:
transform:scale(0.5, 2); -ms-transform:scale(0.5, 2); /* IE 9 */ -moz-transform:scale(0.5, 2); /* Firefox */ -webkit-transform:scale(0.5, 2); /* Safari and Chrome */ -o-transform:scale(0.5, 2); /* Opera */
Skew
Skewing a element will result in the angling of the X and Y axes:
transform:skew(10deg, 20deg); -ms-transform:skew(10deg, 20deg); /* IE 9 */ -moz-transform:skew(10deg, 20deg); /* Firefox */ -webkit-transform:skew(10deg, 20deg); /* Safari and Chrome */ -o-transform:skew(10deg, 20deg); /* Opera */
The following illustration is a representation of skewing an image with the preceding properties:

Matrix
The matrix
properties combine all of the preceding transforms into a single property and can easily eliminate many extra lines of CSS in your source:
transform:matrix(0.586, 0.8, -0.8, 0.586, 40, 20); /* IE 9 */ -ms-transform:matrix(0.586, 0.8, -0.8, 0.586, 40, 20); /* Firefox */ -moz-transform:matrix(0.586, 0.8, -0.8, 0.586, 40, 20); /* Safari and Chrome */ -webkit-transform:matrix(0.586, 0.8, -0.8, 0.586, 40, 20); /* Opera */ -o-transform:matrix(0.586, 0.8, -0.8, 0.586, 40, 20);
The preceding example utilizes the CSS transform matrix property to apply multiple transform styles in a single call. The matrix
property requires six parameters to rotate, scale, move, and skew the element. Using the matrix property is only really useful when you actually need to implement all of the transform properties at once. If you only need to utilize one aspect of element transforms, you will be better off using just that CSS style property.
3D transforms
Up until now, all of the transform properties we have reviewed have been two dimensional transformations. CSS3 now also supports 3D as well as 2D transforms. One of the best parts of CSS3 3D transforms is the fact that many devices and browsers support hardware acceleration allowing this complex graphical processing to be done on your video cards GPU. At the time of writing this book, only Chrome, Safari, and Firefox have support for CSS 3D transforms.
Tip
Interested in what browsers will support all these great HTML5 features before you start developing? Check out http://caniuse.com to see what popular browsers support in a simple, easy-to-use website.
When dealing with elements in a 3D world, we make use of the Z coordinate, which allows the use of some new transform properties.
transform:rotateX(angle) transform:rotateY(angle) transform:rotateZ(angle) transform:translateZ(px) transform:scaleZ(px)
Let's create a 3D cube from HTML elements to put all of these properties into a working example. To start creating our 3D cube, we will begin by writing the HTML elements which will contain the cube as well as the elements which will be making up the cube itself:
<body> <div class="container"> <div id="cube"> <div class="front"></div> <div class="back"></div> <div class="right"></div> <div class="left"></div> <div class="top"></div> <div class="bottom"></div> </div> </div> </body>
This HTML creates a simple layout for our cube by not only creating each of the six sides, which makes up a cube with specific class names, but the container for the entire cube as well as the main container to display all of our page content. Of course, since there is no internal content in these containers and no styling yet, opening this HTML file in your browser would yield an empty page. So let's start writing our CSS to make all of these elements visible and position each to form our three dimensional cube. We will start by setting up our main containers which will position our content and contain our cubes sides:
.container { width: 640px; height: 360px; position: relative; margin: 200px auto; /* Currently only supported by Webkit browsers. */ -webkit-perspective: 1000px; perspective: 1000px; } #cube { width: 640px; height: 320px; position: absolute; /* Let the transformed child elements preserve the 3D transformations: */ transform-style: preserve-3d; -webkit-transform-style: preserve-3d; -moz-transform-style: preserve-3d; }
The container
class is our main element, which contains all of the other elements within this example. After appending a width and height, we set the top margin to 200px
to push the display down the page a bit for better viewing and the left and right margins to auto which will align this element in the center of the page:
#cube div { display: block; position: absolute; border: 1px solid #000000; width: 640px; height: 320px; opacity:0.8; }
By defining properties to the #cube div
, we set the styles to every div
element within the #cube
element. We are also kind of cheating the system of cube by setting the width and height to rectangular proportions as the intention is to add videos to each of the cube sides once we structure and position it.
With the basic cube-side styles appended, its time to start transforming each of the sides to form the three-dimensional cube. We will start with the front of the cube by translating it on the Z axis, bringing it closer to the perspective:
#cube .front { -webkit-transform: translateZ(320px); -moz-transform: translateZ(320px); transform: translateZ(320px); }
In order to append this style to our element in all modern browsers, we will need to specify the property in multiple syntaxes for each browser that doesn't support the default transform
property:

The preceding screenshot shows what has happened to the .front
div after appending a Z translation of 320px. The larger rectangle is the .front
div, which is now 320px closer to our perspective. For simplicity's sake, let's do the same to the .back
div and push it 320px away from the perspective:
#cube .back { -webkit-transform: rotateX(-180deg) rotate(-180deg) translateZ(320px); -moz-transform: rotateX(-180deg) rotate(-180deg) translateZ(320px); transform: rotateX(-180deg) rotate(-180deg) translateZ(320px); }
As you can see from the preceding code, to properly move the .back
element into place without placing it upside down, we flip the element by 180 degrees on the X axis and then translate Z by 320px just like we did for .front
. Note that we didn't set a negative value on the translate Z because the element was flipped. With the .back
CSS styles in place, our cube should look like the following:

Now the smallest rectangle visible is the element with the classname .back
, the largest is our .front
element, and the middle rectangle is the remaining elements to be transformed.
To position the sides of our cubes we will need to rotate the side elements on the Y axis to get them to face the proper direction. Once they are rotated into place, we can translate the position on the Z axis to push it out from the center as we did with the front and back faces:
#cube .right { -webkit-transform: rotateY(90deg) translateZ( 320px ); -moz-transform: rotateY(90deg) translateZ( 320px ); transform: rotateY(90deg) translateZ( 320px ); }

With the right side in place, we can do the same to the left side but rotate it in the opposite direction to get it facing the other way:
#cube .left { -webkit-transform: rotateY(-90deg) translateZ( 320px ); -moz-transform: rotateY(-90deg) translateZ( 320px ); transform: rotateY(-90deg) translateZ( 320px ); }

Now that we have all four sides of our cube aligned properly, we can finalize the cube positioning by aligning the top and bottom sides. To properly size the top and bottom we will set their own width and height to override the initial values set in the #cube
div styles:
#cube .top { width: 640px; height: 640px; -webkit-transform: rotateX(90deg) translateZ( 320px ); -moz-transform: rotateX(90deg) translateZ( 320px ); transform: rotateX(90deg) translateZ( 320px ); } #cube .bottom { width: 640px; height: 640px; -webkit-transform: rotateX(-90deg) translateZ( 0px ); -moz-transform: rotateX(-90deg) translateZ( 0px ); transform: rotateX(-90deg) translateZ( 0px ); }
To properly position the top and bottom sides, we rotate the .top
and .bottom
elements +-90 degrees on the X axis to get them to face up and down, and only need to translate the top on the Z axis to raise it to the proper height to connect with all of the other sides.
With all of those transforms appended to our layout, the resulting cube should look like the following:

Although it looks 3D, since there is nothing in the containers, the perspective isn't really showing off our cube very well. So let's add some content such as a video in each of the sides of the cube to get a better visualization of our work. Within each of the sides, let's add the same HTML5 video element code:
<video width="640" height="320" autoplay="true" loop="true"> <source src="cube-video.mp4" type="video/mp4"> <source src="cube-video.webm" type="video/webm"> Your browser does not support the video tag. </video>
Since we have not added the element playback controls in order to display more visible area of the cube, our video element is set to autoplay the video as well as loop the playback on completion. Now we get a result that properly demonstrates what 3D transforms can do and is a little more visually appealing:

Since we set the opacity of each of the cube sides, we can now see all four videos playing on each side, pretty cool! Since we are already here, why not kick it up one more notch and add user interaction to this cube so we can spin it around and see the video on each side.
To perform this user interaction, we need to use JavaScript to translate the mouse coordinates on the page document to the X and Y 3D rotation of our cube. So let's start by creating the JavaScript to listen for mouse events:
window.addEventListener("load", init, false); function init() { // Listen for mouse movement window.addEventListener('mousemove', onMouseMove, false); } function onMouseMove(e) { var mouseX = 0; var mouseY = 0; // Get the mouse position if (e.pageX || e.pageY) { mouseX = e.pageX; mouseY = e.pageY; } else if (e.clientX || e.clientY) { mouseX = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; mouseY = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; } console.log("Mouse Position: x:" + mouseX + " y:" + mouseY); }
As you can see from the preceding code example, when the mousemove
event fires and calls the onMouseMove
function, we need to run some conditionals to properly parse the proper mouse position. Since, like so many other parts of web development, retrieving the mouse coordinates differs from browser to browser, we have added a simple condition to attempt to gather the mouse X and Y in a couple of different ways.
With the mouse position ready to be translated into the transform rotation of our cube, there is one final bit of preparation we need to complete prior to setting the CSS style updates. Since different browsers support the application of CSS transforms in different syntaxes, we need to figure out, in JavaScript, which syntax to use during runtime to allow our script to run on all browsers. The following code example does just that. By setting a predefined array of the possible property values and attempting to check the type of each as an element style property, we can find which element is not undefined and know it can be used for CSS transform styles:
// Get the support transform property var availableProperties = [ 'transform', 'MozTransform', 'WebkitTransform', 'msTransform', 'OTransform' ]; // Loop over each of the properties for (var i = 0; i < availableProperties.length; i++) { // Check if the type of the property style is a string (ie. valid) if (typeof document.documentElement.style[availableProperties[i]] == 'string'){ // If we found the supported property, assign it to a variable // for later use. var supportedTranformProperty = availableProperties[i]; } }
Now that we have the user's mouse position and the proper syntax for CSS transform updates for our cube, we can put it all together and finally have 3D rotational control of our video cube:
<script> var supportedTranformProperty; window.addEventListener("load", init, false); function init() { // Get the support transform property var availableProperties = ['transform', 'MozTransform','WebkitTransform', 'msTransform', 'OTransform']; for (var i = 0; i < availableProperties.length; i++) { if (typeof document.documentElement.style[availableProperties[i]] == 'string'){ supportedTranformProperty = availableProperties[i]; } } // Listen for mouse movement window.addEventListener('mousemove', onMouseMove, false); } function onMouseMove(e) { // Get the mouse position if (e.pageX || e.pageY) { mouseX = e.pageX; mouseY = e.pageY; } else if (e.clientX || e.clientY) { mouseX = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; mouseY = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; } // Update the cube rotation rotateCube(mouseX, mouseY); } function rotateCube(posX, posY) { // Update the CSS transform styles document.getElementById("cube").style[supportedTranformProperty] = 'rotateY(' + posX + 'deg) rotateX(' + posY * -1 + 'deg)'; } </script>
Regardless of the fact we have attempted to allow for multi browser use of this example, it is worth opening it up in each to see how something like 3D transforms with heavy internal content run. During the time of writing this book, all WebKit browsers were the easy choice when viewing content like this, as browsers such as Firefox and Internet Explorer render this example at a much slower and lower quality output:

Transitions
With CSS3, we can add an effect when changing from one style to another, without using Flash animations or JavaScripts:
div { transition: width 2s; -moz-transition: width 2s; /* Firefox 4 */ -webkit-transition: width 2s; /* Safari and Chrome */ -o-transition: width 2s; /* Opera */ }
If the duration is not specified, the transition will have no effect, because the default value is 0:
div { transition: width 2s, height 2s, transform 2s; -moz-transition: width 2s, height 2s, -moz-transform 2s; -webkit-transition: width 2s, height 2s, -webkit-transform 2s; -o-transition: width 2s, height 2s,-o-transform 2s; }
Tip
It should be worth noting that Internet Explorer currently does not have support for CSS3 transitions.
Browser compatibility
If you haven't noticed yet, the battle of browser compatibility is one of the biggest aspects of a web developer's job. Over time, many great services and applications have been created to help developers overcome these hurdles in a much simpler manner than trial-and-error techniques. Websites such as http://css3test.com, http://caniuse.com, and http://html5readiness.com are all great resources to keep on top of HTML5 specification developer and browser support for all the features within.