\n"); } else { header("Content-type: text/html; charset=utf-8"); } ?> Creating a Framed Picture

Introduction

This page walks you through the process of developing a web page for displaying one picture from a gallery of photographs. There are lots of photobloggers doing this sort of thing, and they use a variety of techniques to achieve some interesting effects, some of which involve Flash and/or Javascript. But this page is different: it uses the photo gallery problem as a context for working with background images.

The background of a box extends from the outer edges of the box’s border inward. A box can have both a background color and a background image. The image is in front of the color, so any transparent part of the image will let the background color show through. For this exercise, we will create a vignette effect. Normally, vignetting is considered a defect caused by a poor quality lens, but some people like to use it as an artistic effect. We will pretend a client has asked us to create this effect for a set pictures being displayed.

In a perfect world, XHTML and CSS code that pass the w3.org validation tests will display the same in all browsers. But the world is not perfect (sorry), and the techniques shown here will produce different results in different browsers. However, these techniques produce nearly identical results in the current (as of the time of writing) versions of Internet Explorer (IE), Firefox, Opera, and Safari. Most notably, the techniques shown here will not produce reasonable results using versions of IE numbered 6 and below. In the real world, this fact would have to be addressed, possibly by detecting the brand and version of the user’s browser and redirecting those users to a different page with fewer features.

XHTML Structure

The pages in this project will have three main sections: a header to hold the name of the picture, a content section to hold the picture itself, and a footer section that will contain two subsections, one for links for navigating through the gallery and another one for links for validating the markup and stylesheet. It is natural to use divs for each of these sections:
<div id="header"> </div> <div id="content"> </div> <div id="footer"> <div id="navigation"> </div> <div id="validation"> </div> </div>

The content section will contain a picture, a vignette surrounding the picture, and a clickable link for going to the next picture in the gallery. There are two choices we need to make: (1) should the picture change size when the user changes the size of the viewport and/or the font size for text? (2) Should the vignette get clipped away when the viewport shrinks, or should it always be present?

For the first choice, our client has said that all pictures in the gallery have to have the same image size, 900×566 pixels, so we will to keep the picture size fixed. This decision makes a big difference in how the page is designed, so the material that follows would have to be much different if the picture needed to be re-sizeable.

Each picture in the gallery is prepared for the web using a program like Fireworks or ImageReady to set the height and width to fit in a canvas with the 900×566 dimensions, with areas of the image that do not fill out to one dimension or the other (or both) set to a color that will match the background color of the content div. When the viewport is large enough for the content div to exceed the intrinsic size of the picture, the background color of the div will show around the picture. For this project, we will use black as the background color, black as the color of the matte surrounding the optimized image, and black as the color of the vignette. You could use any set of matching colors for other effects.

The second decision is about how the vignette effect is to change when the viewport changes. One possibility is to create a vignette image the same size as the photograph and to place it in front of the picture. For example, here is div with a white background, a 900×566 pixel photograph as the background image, and a 900×566 pixel vignette img as the sole content of the div:

Picture with vignette frame

Click this button to toggle the overflow property of the above div between the values, “hidden” and “visible.” When the value is “visible” you will be able to see the right side of the vignette image extending beyond the photograph when the viewport is narrow. When the value is “hidden” you will be able to see that the vignette image does not track the right side of the displayed image.

Click this button to turn the background image for the above div off and on so you can see the vignette image more clearly.

For this project, our client has told us that the above effect is not correct: she wants the vignette to surround whatever part of the picture is visible in the viewport, and the thickness of the vignette is not to change when the user resizes the viewport. While we might question the client’s choice in this matter (but only to ourselves, of course), it gives us a wonderful opportunity to practice working with background repeats and the use of XHTML “scaffolding” to provide access to elements of a page that need special CSS styling. (OK, there is no real client involved here, but we will do the design this way anyway.)

Because neither the size of the photograph nor the thickness of the vignette edges ever changes size, we can use background images for everything. We will use the photograph as the background image for a div, and we will then put four identically-sized divs in front of the image div, and use repeated copies of four small images on each of these four divs to create the four sides of the vignette frame.

Here is an approximation of the effect we are going to set up:

Click this button to turn the picture on and off so you can see what the vignette looks like. Resize your browser’s window to see what is happening.

Note: Before you hide the picture the first time, the background color of the div containing the picture is black, which you will be able to see on the right as you make your browser’s viewport very wide. The first time you hide the picture, the background color is changed to white, and remains white until you reload the page, so you can see the shape of the four vignette frame sides. Note what happens on the right side when the viewport is wide and the background color is white.

The above is only an approximation of the final effect because the structure of this web page does not match the structure of the web page we are developing as outlined above.

Here is the scaffolding for creating five divs that overlay each other. The geometry works because none of the divs has any content:

<div id="content"> <div id="top> <div id="right> <div id="bottom"> <div id="left"> <a href="#"></a> </div> </div> </div> </div> </div>

Without any content in them, these five divs will all collapse to nothingness (their heights will be zero) unless we do something to force their heights to have non-zero values. The a tag inside the innermost div represents the link to the next picture in the photo gallery. Because it has no content, it will also collapse to nothingness at this point. The next section will show how to use CSS to take care of these issues.

Before styling the page you should add an h1 tag containing the picture name to the header section of the project, and all the navigation and validations links to the two footer sections.

Stylesheet Setup

While there are sound reasons for starting with a site-wide style sheet and either modifying it or supplementing it with a new sheet for the picture gallery, we will assume here that there is just one blank stylesheet for this project so we can avoid distractions due to settings that come from somewhere else.

Set up a link to your new stylesheet and initialize the sheet with the following rule:

html, body { background-color: red; color: green; font-family: sans-serif; margin: 0; height: 100%; }

The color and background-color properties are there simply so we can tell if they are in effect when we don’t expect them to be.

The font-family property is a matter of personal preference. Most people think that sans-serif fonts (like Helvetica and Arial) are easier to read on a screen and that serif fonts (like Times Roman) are easier to read on printed pages.

The margin and height properties are very important for getting the page to work correctly. The margins have to be set to zero because by default most browsers put a margin around the content of web pages, which would show up as a red border around the edges of the viewport. The margin setting is necessary because there is no standard for whether the html and/ or body should have a margin or not. Remember, each browser has a default built-in default stylesheet that it uses for displaying page elements in the absence of any other stylesheet rules.

The height attribute, on the other hand, illustrates a basic CSS rule: by default boxes are made large enough to contain their content, and no larger. To get the footer div to stick to the bottom of the viewport, the browser has to make the height of the body match the height of the viewport, no matter how the user decides to resize the browser window. We will also have to give explicit heights to all three of the top leveldivs in the file to keep them from collapsing to nothingness.

The following rules will divide the viewport so that the header, content, and footer divs together fill the entire height of the viewport. The background colors will be the ones used for the sample project being developed here: white text on a black background:

#header { height: 10%; color: white; background-color: black; } #content { height: 75%; color: white; background-color: black; } #footer { height: 15%; color: white; background-color: black; }

With this stylesheet in place, you should be able to view your web page in any of the current browsers and see a black page with the picture name (the h1 content) at the header at the top and the text for the links in the footer at the bottom, regardless of how you change the size of the browser’s window. The red background assigned to the html and body elements should be completely covered. (Actually, Opera and Safari both leave a one-pixel high piece of the background showing along the bottom of the viewport. IE 6 processes this part of the project the same way Firefox does, with no red line at the bottom.) Practically speaking, you could have set the background-color and color properties to black and white for the html and body tags, but then you wouldn’t have seen this “interesting” red line.

Setting an explicit height for the content div is not sufficient for getting the four vignette borders to show up. The heights of the four inner divs and of the a tag must all be set to 100% to make them completely fill their containing boxes without collapsing to nothingness. There is an example of a rule that includes this property setting for the bottom div below.

Background Images

Before adding the picture and its vignette to the project, note that background images are made up of pictures with certain “intrinsic” pixel dimensionalities. That is, the size of a background image is whatever size is built into the image file, and there is no way to change it. (In contrast, images that are part of a page’s content can have their intrinsic sizes altered in a number of ways.) There are two CSS properties for placing background images in a box. The first controls how a background image repeats over the background: horizontally, vertically, in both directions (called “tiling”) or not at all:

illustrate background-repeat property

The second property is the position of the image within the box. The default position is in the top left corner of the box, but (among other options) you can attach a background image to any side of the box, or center it.

Displaying the Photograph

For the photograph, it makes sense to center it as the background image of the content div, with no tiling:

#content { background-repeat: no-repeat; background-position: center; }

But each of the pages in the photo gallery needs to have a different background image for the content div. Rather than create an entire separate stylesheet for each picture with each stylesheet having only one line different from all of the others, we will embed the rule for the background image in the .xhtml file for the picture. For example:

<style type="text/css"> #content { background-image: url(../images/harbor.jpg); } </style>
OPTIONAL If you want to experiment with server-side scripting, the following code will use PHP to generate the name of the background image file based on the name of the .xhtml file that it appears in. For example, it would insert the above code into a file named harbor.xhtml:
<style type="text/css"> #content { background-image: url(../images/<?php echo str_replace( '.xhtml', '.jpg', basename($_SERVER['SCRIPT_FILENAME']) ); ?>); } </style>
Be sure there is no space between the first part of the pathname and the < that starts the <?php tag. The advantage of this approach is that you can use the same code in all the picture files. You just have to be sure the .xhtml filenames match the .jpg filenames.

The Vignette Frame

The strategy for making the background into a picture frame is to have the top and bottom be very narrow images with their heights equal to the thickness of the frame we want and to make them repeat horizontally across the width of the frame. Likewise, the left and right sides will be have widths equal to the thickness of the frame, will be very short, and will repeat vertically along he height of the frame. Practically speaking, “very narrow” and “very short” can be as small as one pixel wide or one pixel high, leading to very modestly-sized image files. But one-pixel thick images images are hard to work with, so we will use rectangles with a smaller dimension of 16 pixels instead of just one. Finally, to create the vignette effect, we will make the frame edges fade to transparency so they will blend with the picture as they go from the outside towards the inside. For example, if the vignette color is black, these four images could be used:

Top: frame_border_pieces.png Right: frame_border_pieces.png Bottom: frame_border_pieces.png Left: frame_border_pieces.png

To show the significance of a gradient fading to transparency, here are the same four images against a tinted background. Instead of fading to white, they now fade to pink:

Top: frame_border_pieces.png Right: frame_border_pieces.png Bottom: frame_border_pieces.png Left: frame_border_pieces.png

You can download copies of the four images by right-clicking on them above, or you can go to the images download page, where you can pick them up along with the SVG files that were used to draw them. You will also see there copies of the full vignette frame files (SVG and PNG) used in the first example on this web page, which you may want to experiment with. You can edit the SVG files using the InkScape program available in the lab. (You can download the current version of this program for free from the inkscape.org web site.)

A final piece of housekeeping is for you to attach each border to the proper edge of its div, using the background-position property. This property defaults to a value of “top left”, so you really only need to specify it for the bottom and right borders:

#bottom { height: 100%; background-image: url(images/borders/bottom_border.png); background-repeat: repeat-x; background-position: bottom; }

But it a good idea to specify it explicitly for all four borders.