The 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!”

Screenshot of portfolioAgain, 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 CSS 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 CSS supported box-shadow and transforms:

<img src="assets/images/milk-and-cookies.jpg" style="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:

var obj = document.getElementById('biopic'),
	// large image always has an id of "biopic"
min = -4, // maximum negative rotation of the picture
max = 4, // maximum positive rotation of the picture
randomRot = Math.floor(Math.random()*(max-min+1)+min);
	// 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:

var rotate = "rotate(" + randomRot + "deg)";
	// formats the rotate amount for the CSS = rotate;
	// transform for Safari = rotate;
	// 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: 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).

var yPos = findPosY(obj);
	// finds the vertical position of the big picture
xPos = findPosX(obj),
	// finds the horizontal position of the big picture
height = parseInt(document.defaultView.getComputedStyle(obj,null).
	// height of the big pic
width = parseInt(document.defaultView.getComputedStyle(obj,null).
	// 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:

var bigoriginy = (height/2);
var bigoriginx = (width/2);
	// 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:

var tape = 
new Array('top_left_corner_tape', 'top_right_corner_tape','bottom_left_corner_tape', 'bottom_right_corner_tape');
for (var i = 0; i < tape.length; i++ ) {
	// do this to all the pieces of tape
	thistape = document.getElementById(tape[i]);
	if (tape[i].match("left")) { 
		// if element ID has the word "left" in it, calculate left of tape as being close to left of the pic = (xPos - 30)+"px"; 
		var originx = bigoriginx; 
		// the x distance of the origin for pieces of tape on the left is the horizontal midpoint of the pic
	if (tape[i].match("right")) { 
		// if element ID has the word "right" in it, calculate left of tape as being close to right of the pic = (xPos + width - 40)+"px"; 
		var originx = "-" + bigoriginx; 
		// the x distance of the origin for pieces of tape on the right is the horizontal midpoint of thebiopicc
	if (tape[i].match("top")) { 
	// if element ID has the word "top" in it, calculate top of tape as being close to top of the pic = (yPos - 40)+"px"; 
	var originy = bigoriginy;
	// the y distance of the origin for pieces of tape at the top is the vertical midpoint of thebiopicc
	if (tape[i].match("bottom")) { 
		// if element ID has the word "bottom" in it, calculate top of tape as being close to bottom of the pic = (yPos + height - 20)+"px"; 
	var originy = "-" + bigoriginy; 
	// the y distance of the origin for pieces of tape at the bottom is the vertical midpoint of the pic, signed negative
	} = originx + "px " + originy + "px";
	// origin format for Mozilla =
	originx + "px " + originy + "px"; // origin format for Webkit = rotate;
	// rotate the tape by the same amount as the pic, for Webkit = rotate;
	// rotate the tape by the same amount as the pic, for Mozilla