demosthenes.info

I’m Dudley Storey, the author of Pro CSS3 Animation. This is my blog, where I talk about web design and development with , and . To receive more information, including news, updates, and tips, you should follow me on Twitter.

featured articles

popular favourites

CSS 3 Transforms and JavaScript

Screenshot of portfolioThe end of the fall semester was particularly disappointing, at least in regards to my second year students . While the usual factors were at play – lack of attention to detail (or lack of any kind of attention at all), tiredness, stress, and rushed, last-minute work – there was something else missing in the final project. I saw a lack of creativity that reflected not just those factors, but a general lack of confidence and fluency in itself.

In response, I started the last winter semester in the completely opposite direction from normal, breaking out multicoloured poster boards and glitter pens and glue, and giving the students only one command: “design!”

Again, some of the results were disappointing (mostly because of lack of innate talent, or because they were terrified of (or unfamiliar with) holding a pen in their hand and being asked to draw), but less so than the efforts of the previous semester.

As part of the goal to inspire and free up their designs, I showed both classes draft pages of my portfolio website – which were inspired, in turn, by their own portfolio sites, and the entirely justified goading of the 1st years to “show us what you can do.” You can see a mockup of the basic design to the left: essentially, I wanted the large portfolio images to appear like Polaroids in a scrapbook. My goal in sharing this with the class was to emphasize that not everything in web design has to be at rigid right angles, or standard top-left navigation configuration, if the changes were logical, consistent, and warranted.

Of course, some of the students took this a little too literally, and started to design everything on their pages at an angle, but on the whole the experiment seems to have been a success. After SAIT’s reading week, my goal is to critique those designs, then turn them into work, and from there explore the and markup necessary to turn them into full web sites.

In the meantime, I continued to work on my own portfolio site. It occurred to me very quickly that the technology behind the design was crude and inefficient. For each image, I was forced to go into PhotoShop, rotate the image, stroke the outside to place a border on it, generate a drop shadow, and place “Scotch tape” layers on the corners, before slicing and exporting it. Of course, PhotoShop actions could automate part of this process, but not all – I wanted the rotation to be essentially random, within a range of 4 degrees positive or negative. Naturally, in order to gain the full effect and preserve the background image in the body behind it, the portfolio image had to be exported as a 24-bit PNG, which ramped up file sizes dramatically.

Considering the problem, I knew I could generate the photo border easily enough with a CSS border property. I also knew that supported box-shadow, albeit implemented slightly differently between Safari and Firefox, while the spec remains in draft. I wasn’t sure that drop-shadow would take into account the border (as it turns out, it did), but my first real problem was rotating the image in the browser.

A glance at a mention of “CSS transforms” and a little research revealed that CSS3 is also pushing towards scale, skew and rotational transforms of elements. Again, easy enough to implement as a fixed style:

  1. <img src="assets/images/milk-and-cookies.jpg"
  2. style="-moz-transform:rotate(5deg); -webkit-transform:rotate(5deg);" />

The visual quality of the rotation in the browser was not as good as doing the same routine in PhotoShop, but it was close enough – and the difference in file size (since I could now save just the portfolio image as a JPEG, without border, Scotch tape or drop-shadow) and workflow efficiency was huge.

But I wanted the rotation to be random, to avoid the website looking predictable and staid. Well, it was easy enough to generate a random number in , in this case between -4 and 4:

  1. var obj = document.getElementById('biopic');
  2. // large image always has an id of "biopic"
  3. var min = -4; // maximum negative rotation of the picture
  4. var max = 4; // maximum positive rotation of the picture
  5. var randomRot = Math.floor(Math.random()*(max-min+1)+min);
  6. // provides a random number between -4 and 4.

The problem then became applying the transformation to the element via JavaScript, rather than CSS. I could have used a library like JQuery to speed things up, but I was determined to do it myself, in just a few lines of code, and this is what I found:

  1. var rotate = "rotate(" + randomRot + "deg)";
  2. // formats the rotate amount for the CSS
  3. obj.style.webkitTransform = rotate;
  4. // transform for Safari
  5. obj.style.MozTransform = rotate;
  6. // transform for Firefox

Success! I could now watch the portfolio image happily twist from side to side with each page refresh. Then, I had to put the Scotch tape in the corners. This proved to be the challenging part. There is talk of future CSS specs allowing element position based on calculation from another element, but that is still very much in draft, and not implemented in any browser that I’m aware of. Lacking that, I needed to find a whole bunch of information about the position of the large portfolio image - it’s height, width, left and right - via JavaScript.

This was made more complicated by the fact that I did not have the large image absolutely positioned: keeping with the tenets of fluid design, I wanted it relative to the list of smaller thumbnails beside it. Future design revisions could also see it nested inside elements, or below others. A little bit of web crawling brought me to this page, which provided a function, which under most (but not all) circumstances, would find the left and top of any element on a page. I also used getPropertyValue to gain the width and height. (And if you’re interested, the width, height, left and right of an object do not change just because an element is rotated – JavaScript draws its data from the original box of the object).

  1. var yPos = findPosY(obj);
  2. // finds the vertical position of the big picture
  3. var xPos = findPosX(obj);
  4. // finds the horizontal position of the big picture
  5. var height = parseInt(document.defaultView.getComputedStyle(obj,null).
  6. getPropertyValue("height")); // height of the big pic
  7. var width = parseInt(document.defaultView.getComputedStyle(obj,null).
  8. getPropertyValue("width")); // width of the big pic

With that known data – the top and left of an object, along with its width and height - I could quickly calculate the corners of the large image (pre-rotation), and absolutely position Scotch tape images in those locations (as a test, I used vector rectangles exported as PNGs from PhotoShop).

The result was great if the portfolio image only rotated a degree or so, but the Scotch tape was visibly out of place if the large image was rotated to its maximum extent. I knew the rotation amount, but the problem was that all transformations happen from the visual centre of an object by default. In other words, the Scotch tape images would rotate like a propeller if the same transformation was applied to them – I needed rotation around the centre of the large portfolio image.

After a silly moment of working out the trigonometry to achieve this, I realized that the wizards of CSS do allow for repositioning the transformation origin of an element anywhere. There are a bunch of keywords for positioning the origin inside the element, but I wanted it outside, in the center of the large image. I knew the width and height of the image, so finding its midpoint was easy:

  1. var bigoriginy = (height/2);
  2. var bigoriginx = (width/2);
  3. // gets the center of the pic horizontally and vertically

Then, I just needed to set the origin of the Scotch tape pieces appropriately and rotate them the same amount as the large image.

The script I had written thus far worked for my test cases of the top left and bottom right pieces of Scotch tape, but repeating lines of code for each transformation would be wasteful. Instead, I made an array based on the ids of the scotch tape pieces. Based on this, a logical naming scheme, and a search to find appropriate words in the id values of the elements, I then had the ability to apply the transformations I needed in a single for loop:

  1. var tape =
  2. new Array('top_left_corner_tape', 'top_right_corner_tape',
  3. 'bottom_left_corner_tape', 'bottom_right_corner_tape');
  4. for (var i = 0; i < tape.length; i++ ) {
  5. // do this to all the pieces of tape
  6. thistape = document.getElementById(tape[i]);
  7. if (tape[i].match("left")) {
  8. // if element ID has the word "left" in it,
  9. calculate left of tape as being close to left of the pic
  10. thistape.style.left = (xPos - 30)+"px";
  11. var originx = bigoriginx;
  12. // the x distance of the origin for pieces of tape on the left
  13. is the horizontal midpoint of the pic
  14. }
  15. if (tape[i].match("right")) {
  16. // if element ID has the word "right" in it, calculate left of tape
  17. as being close to right of the pic
  18. thistape.style.left = (xPos + width - 40)+"px";
  19. var originx = "-" + bigoriginx;
  20. // the x distance of the origin for pieces of tape on the right
  21. is the horizontal midpoint of thebiopicc
  22. }
  23. if (tape[i].match("top")) {
  24. // if element ID has the word "top" in it,
  25. calculate top of tape as being close to top of the pic
  26. thistape.style.top = (yPos - 40)+"px";
  27. var originy = bigoriginy;
  28. // the y distance of the origin for pieces of tape at the top
  29. is the vertical midpoint of thebiopicc
  30. }
  31. if (tape[i].match("bottom")) {
  32. // if element ID has the word "bottom" in it,
  33. calculate top of tape as being close to bottom of the pic
  34. thistape.style.top = (yPos + height - 20)+"px";
  35. var originy = "-" + bigoriginy;
  36. // the y distance of the origin for pieces of tape at the bottom
  37. is the vertical midpoint of the pic, signed negative
  38. }
  39. thistape.style.MozTransformOrigin =
  40. originx + "px " + originy + "px"; // origin format for Mozilla
  41. thistape.style.webkitTransformOrigin =
  42. originx + "px " + originy + "px"; // origin format for Webkit
  43. thistape.style.webkitTransform = rotate;
  44. // rotate the tape by the same amount as the pic, for Webkit
  45. thistape.style.MozTransform = rotate;
  46. // rotate the tape by the same amount as the pic, for Mozilla
  47. }

There are a few improvements I’d like to make: obviously, this only works for recent versions of Firefox and Safari.

Color in CSS

There are four methods of producing color in CSS: keyword, hexidecimal, rgb and hsl. The first two were introduced with CSS Level 1, and are available to every graphical web browser, the last was added in CSS Level 3. rgb and hsl both have an “alpha” derivative that determines opacity (rgba and hsla, respectively.)

Keywords

Color keywords have long been supported by web browsers. 16 of them of them were officially adopted by the W3C as a standard: black, white, aqua, blue, fuchsia, gray, green, lime, maroon, navy, olive, purple, red, silver, teal, and yellow. For example:

  1. body { background-color: white; }

CSS3 expanded this list to create keyword references for 140 “web standard” colors, many of which are somewhat arcane: salmon, aliceblue, and smoke, for example. There are many sources for these color keywords: here is one example.

As a general rule, if given the choice between using color keywords and hexadecimal, choose hex.

Hexidecimal

While color keywords are limited to 140 named colors, the hexadecimal (or “hex”) method is not. Unlike our familiar base-10 system, which uses the integers from 0 to 9, the hexadecimal system has 16 digits: 0 to 9, followed by a to f.

When used to define colors, there are three sets of hexadecimal numbers, representing the red, green, and blue components. Each set consists of two hexadecimal numbers (16 × 16 = 256 possible levels for that color component). So a representation like #ffffff would mean that red, green and blue components were “full on”, creating white. #000000 would be “all off”, creating black, #ff0000 would be a pure red, and #777777 would be grey.

“Web safe” colors are created when the number in each color pair is the same (00, 77, ee, etc), and is therefore the most common form you will find. If that is the case, CSS gives you the option to shortcut the code, so that black becomes #000, red #f00, etc. For example:

  1. p { color: #000; }

The hexidecimal values to not have to be the same for each pair: #3fa027 is a perfectly valid hex color. It is important to understand that hexidecimal allows access to the same gamut as the two other color systems discussed below; the color variety is not greater or less under rgb or hsl. There are even hexidecimal codes for every Crayola color.

rgb

While longer-winded and no more or less accurate than hex, the rgb method is easier to manipulate directly via scripts.

rgb values can be specified as values between 0 and 255:

  1. h3 { color: rgb(100, 18, 255); }

Or as percentages:

  1. h3 { color: rgb(50%, 30%, 100%); }

CSS3 introduces an rgba derivation of this method, in which the a component represents alpha, or opacity, as a floating point number between 0 (fully transparent) and 1 (fully opaque). For example, to produce a div with an id of content and a background-color of red that is half-way transparent:

  1. div#content { background-color: rgba(255,0,0, 0.5); }

hsl

hsl color wheelFinally, CSS3 also adds the hsl method, representing hue, saturation, and luminosity. In theory, this allows developers to modify a color to “deeper” or “lighter” quickly and easily in response to client demands.

Rather than a series of “sliders”, hsl is based on a color wheel, moving from red through yellow, green, blue and violet and then back to red. Hue is therefore given as degrees around this circle, with the starting and ending point, red, being both 0 and 360 degrees. Saturation and luminosity are given as percentages:

  1. div#content { background-color: hsl(10,100%,10%); }

There is also hsla, which uses the same floating-point method for opacity that rgba does.

Media types

One of the significant advantages of CSS is that we can create different style rules to represent our content in different formats, on different devices, or for different users: for example, the display of a web page on a cellphone should be different from that on a 27″ monitor which will be different again from the printed version of that page.

If no media value is specified, style rules are assumed by the browser to apply to every media format and device, at least within reason: handheld devices, such as iPhones, will attempt to scale the web page down, and browsers will usually reverse colors if you are trying to print out a page with a black background and white text to save ink. However, we can be much more precise by specifying different style rules for different devices through different media values:

all (the default), screen (for computer monitors), braille (for braille tactile feedback devices), embossed (for braille printers), handheld (for handheld internet devices such as iPhones and tablets), print, projection, speech (for text-to-speech synthesisers), tty (for teletype terminals), and tv.

Under CSS 1 & 2, different style sheets are created for different media types, and linked to separately:

  1. <link rel="stylesheet" href="styles.css" type="text/css" media=“all” />
  2. <link rel="stylesheet" href="styles_p.css" type="text/css" media=“print” />

Style rules may also be specified to apply to multiple formats at the same time:

  1. <style type=“text/css” media=“screen, handheld” >
  2. </style>

Under CSS3, no separate documents need to be written: styles for other media are added to the stylesheet itself by the use of media queries:

  1. /* styles that apply to everything here */
  2. @media print {
  3. /* styles that are applicable only to print here */
  4. }

It is important to note that a stylesheet defined as all, or with no media definition, will apply to all devices and media types; stylesheets defined after this point for print, etc will be used in addition to the first stylesheet: they do not have to repeat rules already present.

Pseudo-class selectors

Pseudo-class selectors define the appearance of an element in a particular state. Where appropriate, I have linked to examples in this blog. (Note: this entry is currently under revision).

CSS Pseudo-class selectors
Pseudo-class selector Purpose
:linkControls the appearance of an unvisited link. Strongly associated with the a tag, to the point at which the a selector used by itself before a style declaration accomplishes the same thing.
:visitedControls the appearance of visited links
:hoverControls the appearance of an element while it is being hovered over with a mouse or other pointing device. While it is heavily associated with the a tag (IE 6 & 7 only support a:hover) CSS does not explicitly specify this association. In modern browsers, :hover can be applied to any arbitrary element, such as img:hover.
:activeThe appearance of content while the user is clicking on it, i.e. between the mouse button being held down and it being released. Rarely used, since the effect is usually so transient.
:first-childSelects the first child element of a markup sequence. For example, ul li:first-child would specify that the style declaration applies to the first li element in any unordered list.
:last-childSelects the last child element in a sequence.
:nth-child(N)Selects the child in an element sequence iterations of (N), where N is the word odd, even, a number, or a mathematical expression.
:nth-of-type(N)
:focusSelects links that have been reached via keyboard navigation and form elements that are selected, such as text inputs and textareas.
:validThe state of a form element that is considered valid to a defined pattern of characters or numbers.
:invalidThe state of a form element with content that is considered invalid
:checkedSelects form elements that are checked, such as radio buttons or checkboxes.

Note that pseudo-selectors can be strung together: a:visited:hover, for example.

One Container, Many Possibilities: Four Layout Options Using a Single div (With A Sprinkling of CSS3)

As I’ve mentioned in the past, div is one of the most overused and misapplied tags in the HTML lexicon. Every block tag can take on the qualities of a div, so there is nothing particularly special about the element itself. The div tag works best when it is used for what it was intended for, as a container for multiple elements, and in that role, it is very nearly indispensable. We will look at four popular layout options, three of them holding to the principles of fluid design, all using a single div as a container.

All of these layouts use the same basic markup: all that changes is the . The code is as follows:

  1. <h1>Evil, Incorporated</h1>
  2. <ul id=”nav”>
  3. <li><a href=”#”>Home</a></li>
  4. <li><a href=”#”>About Us</a></li>
  5. <li><a href=”#”>Contact</a></li>
  6. </ul>
  7. <h2>We Hate You</h2>
  8. <dl id=”captioned-image”>
  9. <dt>
  10. <img src=”darkman.jpg” style=”width: 240px; 240px;” alt=”Ignatius T. Rowley”
  11. title=”Ignatius T. Rowley” />
  12. </dt>
  13. <dd>Our President and Founder, Ignatius T. Rowley</dd>
  14. </dl>
  15. <p>Let’s just get that right out of the way. We loathe you. Here at Evil
  16. Incorporated we pride ourselves on our lack of customer service. Our helpline
  17. operates at random times, and we use a 20-sided die to determine which call to
  18. answer. Customer interaction is always conducted with maximum amount of
  19. surliness. Our location is extremely difficult to find, and the front door is
  20. laden with traps, some of them lethal.</p>

(Note that I’ve used Loren Ipsum text in a second paragraph to expand the content in the screenshots provided.)

The following CSS remains largely unchanged in all the examples below, and is the base on which everything else is built. You should feel free to use your own images, colours and choice of fonts.

  1. html, body { height: 100%; background-color: #feffee; margin: 0; }
  2. h1 { margin: 0; font-family: "Agenda Bold", "Gill Sans", Helvetica, sans-serif;
  3. text-transform: uppercase;text-align: centre; font-size: 3em; padding: .5em 0;
  4. color: #fff; background-color: #333; text-shadow: 4px 4px 2px rgba(0, 0, 0, 0.2);
  5. font-weight: 700; }
  6. h2 { font-family: "Agenda-Medium", Helvetica, sans-serif; margin-left: 2em; }
  7. ul#nav { background-color: #a33; margin-top: 0; padding: .5em 0; }
  8. ul#nav li { display: inline; }
  9. ul#nav li a { text-decoration: none; color: #fff; padding: .5em;
  10. font-family: "Agenda-Bold", Helvetica, sans-serif; }
  11. dl#captioned-image { float: right; text-align: centre; }
  12. dl#captioned-image dd { margin: 1em; font-style: italic; }
  13. p { font-family: Baskerville, Times, serif; text-align: justify;
  14. margin-left: 5em; margin-right: 2em; }

Please note that the designs that follow are neither unitary nor canonical: they are simply starting points, which you should feel free to embroider upon as your inspiration and creativity takes you. (For my students: duplication of this code for use in assignments or in-class exercises will be frowned upon; in especially egregious cases, copying may lead to charges of plagiarism).

Almost all of the design components shown in the basic page layout are derived from CSS we have discussed previously: a horizontal navigation bar, a captioned image, and float. One new feature is text-shadow on the <h1> element. It’s a simple property with three values: horizontal offset, vertical offset, blur and text-shadow colour.Fluid design, no div required

Fluid design, no div required

Our markup lacks a div at this point, but the page displayed is perfectly acceptable. We could add a div, but it would be redundant at this point and not yield any benefit. There are several issues we might fix, however:

There is an problem with the current design when we resize our browser window. At small sizes – most especially narrow window widths – our design breaks down. While maintaining a goal of fluid design should be a priority, there are limits. We’ll set a min-width on the body itself to limit the point at which this fluidity stops:

  1. html, body { height: 100%; background-color: background-color: #feffee;
  2. margin: 0; min-width: 40em; }

Obviously, this value will change depending on just how fluid you wish the design to be, and the sizes of the element used in the body.

Another possible issue is the fact that the paragraph text wraps under our captioned image. This is an aesthetic choice – wrapped images make the best use of space on our page, but sometimes the designer might want to emphasize positive space in the layout. If that was the case, we still don’t need a div – we just need to restrict the width of the paragraphs and our captioned image. In a fluid design, that width would be typically expressed as a percentage. It may take a little experimentation to determine the optimal value, especially when testing extremes of browser window widths, so the percentages below are simply suggestions.

  1. dl#captioned-image { float: right; text-align: centre; width: 40%; }
  2. p { font-family: Baskerville, Times, serif; text-align: justify;
  3. margin-left: 5em; margin-right: 2em; width: 45%; }

Note that the widths stated are percentages of the overall width of the container element: in this case, the body. Note also that they must add to 100% or less, especially when margin is added to any element. As always, placing temporary CSS borders on elements is helpful to visualize what is happening in your page.

We’ll talk more about columnar layouts in CSS later – for now, let’s move on to graphic elements.

While it is not an issue in the design we have, background images can be problematic in fluid designs, as they are fixed in dimension. The solution is to either stretch them to fit using CSS3, or make the image a seamless repeating background tile.

  1. h1 { background-image: url(skyline.jpg); background-position: bottom centre;}

At extreme window widths, our navigation may appear completely out of alignment with our main heading. This is easy enough to correct:

  1. ul#nav { background-color: #a33; margin-top: 0; padding: .5em 0;
  2. text-align: centre; }

Again, this is an aesthetic choice, and one made with some caution: habituation will cause most users to look for the main navigation on the left side of a page, not the centre. Fluid design, even margin on all sides

Fluid design, even margins on all sides

The easiest div-based layout to achieve. Also the most adaptable div design in regards to differing screen resolutions and browser window size, and the most adherent to the principles of design fluidity we discussed earlier.

After adding appropriate markup to our code, add this to the CSS:

  1. div#container { margin: 5em; background-color: #feffee; padding-bottom: 1em; }

(You’ll want to modify the background-color for the body to an appropriately dark tone).

Note that our percentage widths for the paragraphs and the definition list remain in effect; it’s just that they are now being measured against the containing element of the div, rather than the body. We’ve added a little padding on the bottom of the div to make sure that the paragraph text does not push up against it.

Also, min-width is now more appropriately applied to the div than to the body – in the CSS, remove it from one and apply it to the other.

As you can see, the only purpose our div has is to enclose content separately from our body. Fluid design, centred on page with no top or bottom margin

Fluid design, centred, no margin top or bottom

A simple variation on the previous design, better suited to pages with more content that require an “endless scroll” layout. Technically, the only thing to watch out for is margin-top on the h1 element, which in standards compliant browsers will force the top edge down; in our case, we have set margin on the h1 to 0 from the very beginning.

The default CSS is still in effect; the following is simply added to the existing declarations, replacing properties where appropriate. (Be careful not to duplicate or “double-up” style rules – the more redundant code you have, the harder it is to maintain and change.)

  1. html, body { background-color: #222;
  2. background-image: url('background-line.gif'); }

I’ve used a transparent non-aliased GIF for the body background-image because it gives me the most flexibility – I can change the background-color for the page to create a different look, and the colour will show through the transparent parts of the GIF.

Usually this design assumes that the div presents itself with a little more visual separation from the background. Often, this is accomplished with border-left and border-right on the div. While there’s nothing wrong with that, I decided to enhance this design instead with a CSS3 drop-shadow:

  1. div#container { margin: 0 5em; background-color: #feffee; padding-bottom: 1em;
  2. box-shadow: 12px 0 3px rgba(0, 0, 0, 0.4); }

box-shadow takes the same value sequence as text-shadow, but remains (as of this writing) a draft component of CSS3, and is thus preceded by a browser-specific prefix: -moz for Firefox, -webkit for Safari and Chrome, etc.

Background image used in the body (zoomed by 1600%)

However, we want the same treatment on both sides of our “floating div”, to make the drop shadow effect consistent. This presents a problem: box-shadow can only be used once for an element. If we use it twice, the first instance of the property is ignored. Instead, we separate the first and second shadow with commas:

  1. div#container { margin: 0 5em; background-color: #feffee; padding-bottom: 1em;
  2. -moz-box-shadow: 12px 0 3px rgba(0, 0, 0, 0.4), -12px 0 3px rgba(0, 0, 0, 0.4); }

This projects the shadow in the opposite direction. The one remaining issue is that the shadows stop at different points at the bottom of the page, due to that padding-bottom: 1em in the first div. Move that code from the style declaration for the #container div to #fake-container.

Fixed design, centred, no margin top or bottom

Background image for the container div (before treatment in PhotoShop)

Fluid designs should always be our preference: they give the greatest adaptability to screen size, resolution and user preference. Sometimes, however, a fixed-width design is called for. Usually, this is due to bitmapped content in the layout. It’s almost never a good reason, but it is sometimes necessary. In our case, it’s a background-image we want to add to the container div.

We want this background to be used only once in the div. We also want to keep its position in relationship to the content – the left sigil remains on the left of the page, the right on the right. If we’re not using that means we have to make the width of the container div the same as the image:

  1. div#container { width:800px; background-image: url(‘whole_background.jpg’);
  2. background-repeat: no-repeat; }

While the interior relationship of our design remains in place, there is a problem: our div is left-aligned by default. Generally speaking, we want a fixed-width design to be center-aligned to the browser window. The problem is that we will never know the width of the browser. So the easiest way is to always make the left and right margin on the div constantly equal:

  1. div#container { width:800px; background-image: url(‘whole_background.jpg’);
  2. background-repeat: no-repeat; margin: 0 auto; }

Multiple Background Images In CSS3

Screenshot of fixed-width design with gradients and multiple background imagesBackgrounds are not always perfectly tiled repetitions of images. Sometimes they are single images, such as the background image we used in the fixed-width example in the last entry.

After carefully cropping and optimizing the original source of that background image, we can make the result fairly small – around 15K as a JPEG or PNG-8. While this has been the traditional method, there are a few drawbacks:

  • If the background image is not tiled it tends to lead to fixed-width designs, in order to keep the image in place.
  • Much of the file size of the background image is wasted on whitespace.
  • It is impossible to position the individual components of the image via – you can move the image as a whole, but cannot change the spacing between individual components without re-editing the image in PhotoShop and re-exporting.

In it is possible to set multiple backgrounds for elements, which means that each of these components could be clipped out as a separate image (using PhotoShop’s Slice tool or similar) and positioned independently. It is simply an extension of the existing background-image property:

  1. div#container { background-color: #feffee;
  2. background-image: url(images/sigil_1.jpg),
  3. url(images/sigil_2.jpg), url(images/sigil_3.jpg);
  4. background-repeat: no-repeat;
  5. background-position: 2em 2em, right 100px, 12em 10em; };

Note that the images and their positions are listed in order, separated by commas. Also note that images can overlap each other. This now makes it possible to move the background images separately, and, if you wish, make the design fluid once more.

Linear Gradients In CSS3

Screenshot of fixed-width design with gradients and multiple background imagesModern browsers (Firefox 3.6+, Safari 4+, all versions of Chrome, Opera 10+ and IE 10) support gradients in . The syntax for gradients has seen many iterations, improvements and variations since it was first proposed by Apple in 2008; this article focuses on the final unprefixed specification for linear gradients, which is supported in Firefox 15 and IE10 (at least as of this writing). Older browsers will require prefixed values and variations on the syntax, or an solution; I suggest using one of the gradient generators at the end of this article to create the full range of values to support all browsers.

At its most basic, the syntax for a linear gradient is very simple:

  1. body { background-image: linear-gradient(to bottom, #a00, black); }

Linear gradients have just three required values: direction, starting color and ending color. The direction is specified as a keyword for a side (top, left, bottom, right), a pair of keywords to represent a corner (bottom right, for example) or an angle. If keywords are used, they must be preceded by to; angles are specified in the same way as CSS transforms, as bearing directions (i.e. 0deg is north, or the 12 o'clock position, with angles growing to the right (clockwise)).

The color values may be specified as keywords, hexadecimals, rgb, rgba, or hsl values.

While gradients are technically images, and should be applicable anywhere images are used on a web page, most browsers currently support the use of gradients only in backgrounds, so it is that use that I’ll show here.

  1. body { background-image: linear-gradient(45deg, #a00, black); }

By default, colors are equally distributed along the gradient – in this case, red at the starting position (0%), black at the end (100%). If we add intermediary colors, they will be evenly distributed along this continium. If we want to add stops – for example, to have black start from the ⅓rd point, do the following:

  1. body { background-image: linear-gradient(to bottom, #a00, black 33%); }

You can add as many colors as you wish into this gradient, each with their own individual stops – in fact, you could copy them directly from ’s gradient tool. Examples of pop art backgrounds with CSS3As they are treated as just another image, it's entirely possible to combine gradients with background images, as I did in my Pop Art CSS3 Backgrounds article.

Note that gradients will automatically extend the complete height and width of the element, without repeating. Visual misapplication of gradients is often due to not having the element sized correctly: this is especially true in the body, which often needs a min-height: 100% declaration in order to have the gradient extend fully to the bottom of the browser window. Repeating linear gradients are their own, related specification, and will be covered in a separate article.

web developer guide

featured comment

by Aisling Brock in New Business Card Design

what i'm reading

A Feast for Crows: A Song of Ice and Fire: Book Four
A Feast for Crows: A Song of Ice and Fire: Book Four

what i'm watching

Prometheus: Collector's Edition (Bilingual) [Blu-ray 3D + Blu-ray + DVD + Digital Copy]
Prometheus: Collector's Edition (Bilingual) [Blu-ray 3D + Blu-ray + DVD + Digital Copy]

what i'm playing

Borderlands
Borderlands

what i'm hearing

Planets
Planets

blogs

podcasts

no ads ever

This blog is free of advertising, and always will be.

creative commons licensed

The content of this blog is free to use in whatever way you wish under the Creative Commons license.