Backwards-Compatible CSS Gradients

I’m a big fan of content over images in a website. That’s not to say that all images or graphic-based content is bad; I just believe much of what a designer wants for a website, and what is actually required to make that happen, are two completely different things. Many years ago, I was a child of the “table-based” design principals championed by slicing-capable programs like Fireworks and (unfortunately) GoLive.

Graphic-based “table websites” load slowly, have the sliced-up feel to them, and frankly just look ugly. It’s taken a long time to break myself of the bad habits perpetuated by programs like these, and to see that I could build sites from a rendering using only a fraction of the images I would have used to. Over time, I will add more and more of the techniques I’ve learned to this, and today I want to focus on one of the most important: gradients.

Gradients are everywhere, in every design you’ve probably ever seen. Because of these, it is sometimes harder to not use images, but not impossible. Recent advances in browsers capabilities have allowed for CSS gradients to become prominent features in a site’s design. Of course, not everybody has upgraded to state-of-the-art browsers, so we will have to use a variation of “Fallback Declarations” again in order to tastefully degrade your site to the capabilities of older browsers. Here’s the code:

Markup:

CSS:

#gradient_box {
	/* Simple visual properties */
	height: 100px;
	width: 100px;
	border: solid 2px black;

	/* Gradient code */
	background: #FF0000;
	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FF0000', endColorstr='#00FF00');
	background: -webkit-linear-gradient(top, #FF0000, #00FF00);
	background: -moz-linear-gradient(top, #FF0000, #00FF00);
	background: -o-linear-gradient(top, #FF0000, #00FF00);
}

Here’s an example of how it will look.

The code here is simple. First, you set the background color, establishing a base-level color for the element. After that, you add the IE-specific declaration filter. For this tutorial, I chose the “gradient” filter, but a full list of the different available filters for IE can be found here. Then, you add the vendor-specific prefixes (webkit, mozilla, and opera) and you’re done. Very simple!

One quick note, while these features are not fully supported (waiting on you IE), you can add more colors to your gradient by adding more color codes to the end of the list. linear-gradient(top, #FF0000, #00FF00) becomes linear-gradient(top, #FF0000, #00FF00, #0000FF) and so on. You can also use transparency by using rgba values, assuming your browser is in the 21st century, of course.

Posted in CSS | Tagged , , , | Leave a comment

Javascript-Free Image Desaturate

While designing my portfolio page, I wanted to bring in a simple desaturate effect to my images. After a little searching, I found that this seemed to be a very easy task, so long as I was using some kind of Javascript framework. This seemed to be a bit overkill for my purposes so I set to trying to find a pure (no script) way to accomplish this task. After some research, I found my method: CSS Transitions.

Over the last year or so, the capabilities of web browsers have risen to accommodate the basic use of CSS Transitions in every up-to-date browser. These include size, position, and for the purposes of this tutorial style.

For this tutorial, you need 4 things: some markup, a little CSS, and two images, one a de-saturated version of the other. To see a demonstration, check out my portfolio.

Images:

Markup:

CSS:

div.image {
	position: relative;
	width: auto;
	height: 100px;
	float: left;
	border: solid 2px #333;
}

div.image img {
	position: absolute;
	display: block;
	top: 0;
	left: 0;
}

div.image:hover img.bw {
	opacity: 0;
	-webkit-transition: opacity .1s linear .1s;
	-moz-transition: opacity .1s linear .1s;
	-o-transition: opacity .1s linear .1s;
	transition: opacity .1s linear .1s;
	visibility : hidden;
}

div.image img.bw {
	z-index: 21;
	-webkit-transition: opacity .1s linear .1s;
	-moz-transition: opacity .1s linear .1s;
	-o-transition: opacity .1s linear .1s;
	transition: opacity .1s linear .1s;
	visibility : visible;
}

div.image img.color {
	z-index: 20;
}

One thing I should explain at this point is that the code in this tutorial does not really transition “between” the two images, but rather creates the illusion of a between transition. We accomplish this by positioning the two given images on top of one another and then adjusting the opacity property of the “top” black-and-white image, revealing the “bottom” colored image. In order to better explain this, let’s break everything down to two separate problems: we need to position the images on top of one another, and we need to be able to transition between the two.

First, you can position two items on top of each other using a little-known CSS trick. Normally, when using the code position: absolute in CSS, it causes the element to jump out of the flow of a website and set its positioning based on the origin point (0,0) of the browser. This usually is the top-left of a browser, causing all kinds of problems for center-oriented or fluid-width websites. Now, with this trick, you can fool the browser and change the origin point for any object.

Starting with the container (Line 1, markup and css), set your CSS to position: relative, then for any children of the container, you set position: absolute. This may seem counter-productive, having differing style declarations, but what this does is actually reset that origin point, making it the top-left of that element, rather than top-left of the browser. From there, a left: 0 and a top: 0 for both items will place both items in the same place, on top of each other. Then, to choose which image would be on top, you set your z-index value. Here, I chose black-and-white to be over the color, by setting the z-index value for color lower than black-and-white.

Now that we have position down, let’s turn to the transition. Because this is not a fully supported feature across all browsers, some care and planning usually has to go into any CSS declaration. First, we want this transition to trigger on hovering (or “rolling”) over the image and there are two images for which to account, so we need to look to the parent element for our trigger. The style selector at line 16 makes use of the :hover pseudo-selector. This tells the browser to use the declarations contained within only if the user have hovered over that element. Since we know this element will contain the two images, we now have our trigger selected out. From there, we add our declarations.

If you want your style to “work” in as many environments as possible, you have to use what I call fallback declarations. Think of Fallback Declarations as synonyms of a normal declaration; they only go into effect if the first declaration is read as invalid. These types of declarations are usually (but not always) a type of declaration called a vendor prefix declaration. As a browser parses CSS declarations in a given style, it moves from top to bottom looking for styles that it recognizes.

For our purposes, let’s look at the style starting at line 16. The transition fallback begins on the second declaration (line 18) with a series of vendor prefix declarations. As the browser parses the declarations, it will either grab its specified declaration, or fall to the next line. After the vendor prefixes, we have the actual CSS3-standard transition declaration. Eventually, the 3 lines of vendor-specific redundancy will not be needed, but for now we must allow for browsers who have yet adopted CSS3. The final line is the “ancient-browser” fix, not even bothering with the opacity property, and opting to either just be visible or not.

From here, we’ve only transitioned to one image, but not back the other way. This is where we set up a similar non-pseudo style block (line 25) that the browser will use for the hover (or “roll”) out event. The only differences between the two style blocks is that one (the hover block) sets opacity of the image to 0% while the other (the non-hover block) returns opacity to 100%. The work’s already done, you just need a little copy/paste and some small changes and you have a JavaScript-free image desaturate effect.

Posted in Web Design | Tagged , , , | Leave a comment

How to Extract and Play Part of an MP3 in PHP

One of the sites I manage, Late Night Record Pool, has been having bandwidth issues as of late. They enjoy roughly 8,000 unique visits a month, and with the ability to preview any song or video in their extensive library, the bandwidth adds up fast. We didn’t want to give up this awesome feature to the site, but we had to do something. So, I decided to try and come up with a way to just preview the songs, sending out only a fraction of the bandwidth every time.

There are tons of classes and programs that offer up the ability to extract a section from an MP3, but they all require you to save the file before using it. That’s a good method, but with a library of music approaching two terabytes, suddenly adding a preview-version of every song would not be feasible. I had to come up with a way on my own to do it on the fly.

$getID3 = new getID3();

$id3_info = $getID3->analyze($filename);

list($t_min, $t_sec) = explode(':', $id3_info['length']);
$time = ($t_min * 60) + $t_sec;

$preview = $time / 30; // Preview time of 30 seconds

$handle = fopen($filename, 'r');
$content = fread($handle, filesize($filename));

$length = strlen($content);

if (!$session->IsLoggedIn()) {
	$length = round(strlen($content) / $preview);
	$content = substr($content, $length * .66 /* Start extraction ~20 seconds in */, $length);
}

header("Content-Type: {$id3_info['mime_type']}");
header("Content-Length: {$length}");
print $content;

Note: the site from which I’m pulling this example also uses the getID3 PHP library to get information like Artist, Title, Mime-Type, etc.

Now that you’ve read over the code, let’s go back and look at the important lines. Lines 5 and 6 break down the runtime of the entire song (in minutes:seconds) to give us the total number of seconds. From there, a little math on line 8 to get us the exact proportion 30 seconds would be on this song.

Next, we bring the MP3 file into the code; Lines 10 and 11 use the fread method to read the file into the variable $content. We now have a (very large) string representing the MP3. After we pull the file in, and if the user is a logged-in user, we simply output our headers and print this string out. Because of the headers and string we send, the browser will interpret the script as an actual MP3 file and start playing/downloading.

The IF block starting at line 15 handles the preview functionality for users who are not logged in. Using the proportion value we found at line 8, we then calculate out how many bytes will equal 30 seconds for this particular song, and we substr it out. From there, the script is the same as if the user were logged in: output the header, print the string, and the browser will treat it like a new (and shorter) MP3.

Now that I’ve covered how this works, I’d like to explain quickly why it works. An MP3 file is set up so that all meta information (artist, title, length, etc.) are stored at the beginning of the file. This is what’s know as an ID3 tag. The reason the file is structured this way is so that music players can stream and play MP3 files while downloading, rather than having to download the entire song first before playing. With this method of extraction, I can send over all the headers manually to treat it like an MP3, but only send a fraction of the file itself and the browser still plays the song. (Note: line 21 represents the ‘size’ of the file and has to be sent or this will not work)

Obviously, this quick-and-dirty method of extraction does not take into account the ID3 tag. Since I already get this information from my getID3 library, I decided to start the extraction roughly 20 seconds in, bypassing any ID3 code. It also allowed me to start the preview further in the file, making it more likely the user gets to hear the chorus (or hook) of a song in this preview. You can always dial these setting to taste, and the lines to do that (lines 8 and 17) are denoted with comments.

The next step is to work out how to pull the ID3 out first, make the extraction, then add ID3 back on. So, check back for that article in the near future.

Posted in PHP, Web Design | Tagged | Leave a comment