Creative Christmas Gift For Geek Lovers – Web & Mobile App

Posted in News, Web Design3 years ago • Written by

Oh, Christmas. The magic time when you spend all the money you’ve been saving the whole year. Oh, and we have all that Christmas Spirit, of course.

Now, you probably want to spend a lot on your soul mate’s gift, to show her how deep is your love.

Yeah, money can buy cool things, but guess what: almost every year I make my own gifts for my girlfriend (but I always have to buy something else anyway). And I feel that she just loves when I do something by myself instead of just buying it (unless shoes, she wouldn’t like if I made her a shoe). So I’ll show you, dear Padawan, how to make a cool one-page-gift for anybody that you like.

Our goal here is to do a simple “slider”, where a lot of messages and pictures that you like are shown. In the meantime you’ll learn a little bit about design, jQuery and CSS3.

So, let’s rock!

Demo & Download


This is our final effect. You can check out our live demo and download our source files and start playing with it.

Design stuff


First of all we’ll need a cool background. Snow is not an option for me, since in Brazil we barely know what it’s like. So I’d rather pick a cool christmas tree and change it a little. I’ve found a couple of cool images to use in
Salman’s article full of Christmas resources. I’ve chosen one of them, adjusted its colors, sliced its background and cut the Christmas tree itself.

As our effect’s start point (slider and this stuff) we’ll use a rocking tutorial on how to do an Amazing Slideshow (John Lennnon Tribute). We’ll change it a little bit, but the main effect is just amazing :)

Now we need a good looking font for our design. I suggest you to go with Cartoon. Then just generate its webfont and we can include it in our basic HTML (that one downloaded from Rocking Code).

Our basic HTML will be like this:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />

<title>Happy Christmas!</title>
<meta name="description" content="Cool DIY Christmas Gift for geek lovers." />
<meta name="author" content="Rochester Oliveira - 1stWebDesigner.com" />
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico">

<link rel="stylesheet" href="css/style.css?v=2" />
</head>
<body>
<div id="tree">
<div id="container">
<h1>Happy Christmas!</h1>
<div id="masonry">
<div>
<img src="http://placekitten.com/200/300" alt="Cute kitten - http://placekitten.com/200/300" />
<div>Caption text.</div>
</div>
[... more .item divs]
</div>
</div>
<!--! end of #container -->
</div>
<!-- JavaScript at the bottom for fast page loading -->

<!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if necessary -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js"></script>
<script>window.jQuery || document.write("<script src='js/libs/jquery-1.7.1.min.js'>\x3C/script>")</script>

<!-- scripts-->
<script src="js/jquery.images.loaded.js"></script>
<script src="js/jquery.masonry.min.js"></script>
<script type="text/javascript">
//[slideshow action scripts]
</script>
<!-- end scripts-->

</body>
</html>

And basic CSS:

body {
	background: #feffef url("../img/bg.jpg") repeat-x center bottom;
 }
 #tree {
	position: relative;
	width: 100%;
	height: 100%;
	background: #feffef url("../img/bg-tree.jpg") repeat-x center bottom;
 }
#container {
	position: relative;
	width: 880px;
	margin: 15px auto;
	padding: 20px 20px 20px 30px;
	background-color: transparent;
	background-color: rgba(255,255,255,0.5);
	filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#32ffffff,endColorstr=#32ffffff);
	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#32ffffff,endColorstr=#32ffffff)";
	-moz-box-shadow: 0 0 5px #B8B8B8; /* Firefox */
	-webkit-box-shadow: 0 0 5px #B8B8B8; /* Safari, Chrome */
	box-shadow: 0 0 5px #B8B8B8; /* CSS3 */
}
	#container h1 {
		font-family: 'CartonSlab';
		font-size: 20px;
	}
	.item {
		position: relative;
		padding: 0;
		width: 200px;
		margin-bottom: 20px;
		float: left;
		background: #000;
		overflow: hidden;
	}
		.item img {
			width: 100%;
			cursor: pointer;
		}
	.selected {
		border: 2px solid #fff;
		-moz-box-shadow: 0 0 3px #000; /* Firefox */
		-webkit-box-shadow: 0 0 3px #000; /* Safari, Chrome */
		box-shadow: 0 0 3px #000; /* CSS3 */
	}

As you may have noticed, our tree is done with a different HTML element, so it won’t affect our slideshow effect at all.

Oh, and don’t forget to generate favicons. They are really cool.

Setting up pictures and captions


One thing that will really impress your date is to choose romantic messages and cute stuff. So be ready to search for:

  • Cat pictures (demo with a lot of them)
  • Hearts
  • Landscapes
  • Your own pictures

I’ve found a couple of good quotes on QuotationsPage & RomanticloveMessages and have written my own ones (this is really important).

Then, let’s put them inside our HTML with proper markup. We’ll have captions positioned on top, middle and bottom, this way:

<div>
<img src="http://placekitten.com/200/300" alt="Cute kitten - http://placekitten.com/200/300" />
<div>You may not care for me like I care for you But if you ever need me, I will always be around for you.</div>
</div>
<div>
<img src="img/kitten.jpg" alt="Cute kitten - http://www.sxc.hu/photo/1369754" />
<div>It's hard to tell your mind to stop loving someone when your heart still does. </div>
</div>
<div>
<img src="img/kitten1.jpg" alt="Cute kitten - http://www.sxc.hu/photo/555320" />
<div>Meeting you was fate, but falling in love with you was beyond my control. </div>
</div>

And CSS will be:

.item .caption {
	position: absolute;
	top: 0;
	padding: 10px 20px;
	font-family: 'CartonSlab';
	font-size: 15px;
	color: #ffffff;
	background-color: transparent;
	background-color: rgba(0,0,0,0.5);
	filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#32000000,endColorstr=#32000000);
	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#32000000,endColorstr=#32000000)";
}
.item .bottom {
	top: auto;
	bottom: 0;
}
.item .middle {
	top: 50%;
}

Coding Slideshow JS


Our basic logic will be:

  • It’ll hide all captions and reduce opacity for images on start;
  • It’ll automatically expand box and show caption, one at a time;
  • When hovering images, it’ll increase its opacity and automatically stop our timer;
  • When the person clicks on an image, it’ll expand its box;

First, we’ll make sure that no function will run before all images are loaded (it wouldn’t look good, trust me). This code will do the trick (since we’ve uploaded jquery.images.loaded.js):

//defaults
var $container = $('#masonry'), $items = $container.find(".item"), count = $items.length, current = 0, lowOpacity = 0.3, highOpacity = 1, timer = "";

$container.imagesLoaded(function(){
	$container.masonry({
		itemSelector : '.item',
		columnWidth : 220,
		isAnimated: true
	});

	init();
});

This init() will do our first, third and fourth bullet points. Let’s go through it:

function init() {
	//let's set all images to dark and bind their hover
	$items.find("img").each(function(index){
		//hide captions
		$($items[index]).find(".caption").fadeOut();
		//images setup
		$(this)
			.animate( { opacity: lowOpacity } )
			.hover(
				function(){
					$(this).stop().animate( { opacity: highOpacity } );
					stopTimer();
				}, function() {
					startTimer();
					if(index != current) {
						$(this).stop().animate( { opacity: lowOpacity } );
					}
				}
			)
			.click(
				function() {
					expand(index);
				}
			);
	});
	expand(0);
	startTimer();
}

The coolest thing here is all those chained functions. They improve performance a lot and if you break lines between them (always before “.”) it’ll be much better to understand.

Now we have two important functions, startTimer() and stopTimer(). I’m pretty sure you know what do they do. We’ll use setInterval and clearInterval to control our timer:

function startTimer() {
	timer = window.setInterval( "next()", 6000); // it'll call next function every 6 seconds and will identify this interval as "timer"
}
function stopTimer() {
	clearInterval(timer); //we'll kill timer :(
}

Now we called “next” function every 6 seconds let’s see what it does:

function next() {
	//if we add one item to current we'll still below our total count of numbers?
	if ( (current ++) < count) {
		expand(current++);
	} else {
		expand(0);
	}
}

Now what you’ve been waiting for: expand()

//this is what makes our current box bigger and the ones before it smaller
function expand(item) {
	var curItem = $(".selected"), $img = "";
	if(curItem) {
		curItem.animate({"width": "200px"}, function(){
			$img = $(this).find("img");
			imgOff($img);
			curItem.find(".caption").fadeOut();
		}).removeClass("selected");
	}
	$( $items[item] ).animate( {"width": "420px"}, function(){
		$img = $(this).find("img");
		imgOn($img);
		$(this).addClass("selected");
		$container.masonry( 'reload' );
		$($items[item]).find(".caption").fadeIn();
	} );
	current = item;
}
/*** functions used above **/
//let's make our current imag look better
function imgOn(img) {
	img.each(function(){
		$(this).animate( { opacity: highOpacity } );
	});
}
//let's turn off these images
function imgOff(img) {
	img.each(function(){
		$(this).animate( { opacity: lowOpacity } );
	});
}

Ok, then, let’s group all this stuff inside one script call, and we’re done!

var $container = $('#masonry'), $items = $container.find(".item"), count = $items.length, current = 0, lowOpacity = 0.3, highOpacity = 1, timer = "";
$container.imagesLoaded(function(){
	$container.masonry({
		itemSelector : '.item',
		columnWidth : 220,
		isAnimated: true
	});

	init();
});
//runs qwiki function for fisrt item so we'll start loop
function init() {
	//let's set all images to dark and bind their hover
	$items.find("img").each(function(index){
		//hide captions
		$($items[index]).find(".caption").fadeOut();
		//images setup
		$(this)
			.animate( { opacity: lowOpacity } )
			.hover(
				function(){
					$(this).stop().animate( { opacity: highOpacity } );
					stopTimer();
				}, function() {
					startTimer();
					if(index != current) {
						$(this).stop().animate( { opacity: lowOpacity } );
					}
				}
			)
			.click(
				function() {
					expand(index);
				}
			);
	});
	expand(0);
	startTimer();
}
function startTimer() {
	timer = window.setInterval( "next()", 6000);
}
function stopTimer() {
	clearInterval(timer);
}
// let's go on with next item if we didn't reach end of our set of items
function next() {
	if ( (current ++) < count) {
		expand(current++);
	} else {
		expand(0);
	}
}
//let's make our current imag look better
function imgOn(img) {
	img.each(function(){
		$(this).animate( { opacity: highOpacity } );
	});
}
//let's turn off these images
function imgOff(img) {
	img.each(function(){
		$(this).animate( { opacity: lowOpacity } );
	});
}
//this is what makes our current box bigger and the ones before it smaller
function expand(item) {
	var curItem = $(".selected"), $img = "";
	if(curItem) {
		curItem.animate({"width": "200px"}, function(){
			$img = $(this).find("img");
			imgOff($img);
			curItem.find(".caption").fadeOut();
		}).removeClass("selected");
	}
	$( $items[item] ).animate( {"width": "420px"}, function(){
		$img = $(this).find("img");
		imgOn($img);
		$(this).addClass("selected");
		$container.masonry( 'reload' );
		$($items[item]).find(".caption").fadeIn();
	} );
	current = item;
}

Personal touch: My horrible voice as background music


I’ve been learning guitar for 1 month. I know how to play two songs (“In spite of all the danger” and “Stand by me”) and I sing really, really bad. But when I showed my girlfriend my first “demo” record, well, I understood why so many guys want to learn guitar.

This is my final personal touch, and you could do so with a cool picture, a recorded mesage (video, maybe), or whatever you can imagine.

What do you think?


So, have you liked it? Are you planning to do something really special to the ones you love most? Let me hear your thoughts!

43 Written ArticlesWebsiteGoogle+

I'm a web designer and entrepreneur from Itajubá (MG), Brasil. I love writing about obscure topics and doing some cool stuff. And also I do some FREE stuff, check it out: http://www.roch.com.br/

54.83.238.48 - unknown - unknown - US