How to Create CSS3 Christmas Tree Ornaments

How to Create CSS3 Christmas Tree Ornaments

In this guide, we will display the power of CSS3 in drawing complex shapes. We will magically create Christmas tree ornaments using only CSS3 and HTML (no images). In particular, we will be drawing baubles, which are the hallmark ornamentation of Christmas trees.

Note that this is merely a fun, proof-of-concept that explores the possible applications of CSS3. If you intend to use this in production, you should be aware that what we will be creating uses W3C specifications that are not yet, or will never be, supported in many browsers (such as IE6 through IE8). Also, the markup must be updated in order to avoid empty div elements.

CSS Ingredients

Before we get started, let’s just quickly go over what we be using.

  1. :before and :after pseudo-elements: Using pseudo-elements will help us in reducing the amount of unnecessary HTML we need to use. If you have worked with rounded corners in CSS2 before, you probably know that, in order to produce flexible rounded corners that accommodate various sizes of content, you had to use a lot of empty divs and such. By using these elements, we will have minimal markup. In this case, just one empty div per bauble, which, if you were enterprising, you would fill with some text content. Note that these pseudo-elements are in CSS2 specs.
  2. CSS3 linear and radial gradients: To get the metallic color fills and shines of the baubles, we will use color gradients.
  3. Box shadows, transformations, border radius, etc.: To create the shapes, we will be using a combination of box-shadow, transform, and border-radius (for rounded corners).


First, let us create the markup. As you can see below, the structure is quite minimal and contains only the minimum amount of markup necessary.

Since the globes need to be block elements, I chose to go with <div> instead of <span>, however, if you are not comfortable with that, you can use <span> tags and then use the display: block CSS property/value pair.

I have placed them in an unordered list because I decided that they are a group of items with no particular hierarchy (e.g. red-bauble is not greater than green-bauble), and so, to me, the metaphor of unordered lists is retained.

<ul id="bauble-container">
    <div class="bauble red-bauble"></div>
    <div class="bauble blue-bauble"></div>
    <div class="bauble yellow-bauble"></div> 
    <div class="bauble green-bauble"></div>

Explanation of the IDs/classes:

  1. #bauble-container is our unordered list, which will be used for targeting the list items (<li>) with greater specificity.
  2. .bauble is the main part of the ornament; the spherical shape.
  3. .red-bauble, .blue-bauble, .yellow-bauble and .green-bauble are the classes used for adding color variations. It makes our work flexible so that, if you wanted various combinations, you’re not stuck with the color combinations I chose. For example, you could have two yellow baubles or no yellow baubles–that’s why we use classes, and not IDs, for these.


What follows are the style rules that will turn our boring unordered list above into a magical set of Christmas tree ornaments.

For discussion, I have commented the CSS below so that you can see how it works to highlight the major parts of the CSS.

Note that, in production, you would not want this much commenting in your stylesheet because it is over the top and because it can increase your stylesheet’s file size.

/* General */
	background: #f2f5f6; /* Fallback background color if gradients are not supported */
	background: -moz-linear-gradient(top, #f2f5f6, #c8d7dc);
	background: -webkit-gradient(linear,left bottom,left top,color-stop(0, #c8d7dc),color-stop(1, #f2f5f6));
	height: 100%;

  list-style: none; /* Remove bullets */
  width: 568px;  
  margin: 150px auto; /* Center it */
  padding: 0; /* In production, this may not be needed if you reset your styles in your global stylesheet:

#bauble-container li
  margin: 0 20px; /* let's add some space */
  float: left; /* place them in line */

/* This is the part where the Christmas bauble string is added */
#bauble-container li:before
	content: "";
	background: #dadada; /* Fallback */	
	background: -moz-linear-gradient(bottom, #9c9c9c, rgba(255,255,255,0) );
	background: -webkit-gradient(linear, left bottom, right top, from(#9c9c9c), color-stop(100%, rgba(255,255,255,0))); 
	height: 50px;
	width: 2px;
	display: block;
	margin: 0 auto;

/* Alernatively rotate them */
#bauble-container li:nth-child(odd)
	-moz-transform: rotate(-5deg); /* Firefox */
	-webkit-transform: rotate(-5deg); /* Chrome and Safari */
	-o-transform: rotate(-5deg); /* Opera */
	-ms-transform: rotate(-5deg); /* Surprise! IE9 with its own prefix */

#bauble-container li:nth-child(even)
	-moz-transform: rotate(5deg);
	-webkit-transform: rotate(5deg);
	-o-transform: rotate(5deg);
	-ms-transform: rotate(5deg);

/* Style the bauble */
	-moz-border-radius: 100px;
	border-radius: 100px;
	-moz-box-shadow: 0 0 5px #777777;
	box-shadow: 0 0 5px #777777;
	-webkit-box-shadow: 0 0 5px #777777;
	border: 1px solid rgba(0,0,0,0.3);
	position: relative;
	height: 100px;
	width: 100px;  

/* Style the bauble head */
	content: "";

	background: #fff; /* Fallback */	
	background: -moz-linear-gradient(left, #fff, #9c9c9c, #fff, #9c9c9c );
	background: -webkit-gradient(linear, left center, right center, from(#fff), color-stop(25%, #9c9c9c), color-stop(50%, #fff), color-stop(75%, #9c9c9c)); 
	-moz-border-radius: 2px;
	border-radius: 2px;
	-moz-box-shadow: 0 1px 0 rgba(0,0,0,0.2), 0 -1px 0 rgba(255,255,255,0.3) inset;
	box-shadow: 0 1px 0 rgba(0,0,0,0.2), 0 -1px 0 rgba(255,255,255,0.3) inset;
	-webkit-box-shadow: 0 1px 0 rgba(0,0,0,0.2), 0 -1px 0 rgba(255,255,255,0.3) inset;
	border: 1px solid #dadada ;
	height: 10px;
	width: 20px;		
	position: absolute;
	left: 50%;
	top: -12px;
	margin-left: -10px;

/* Add bauble light reflection */	
	content: "";
	-moz-border-radius: 100px;
	border-radius: 100px;
	background: #fff; /* Fallback */	
	background: -moz-linear-gradient(bottom, #fff, rgba(255,255,255,0.1) );
	background: -webkit-gradient(linear, left bottom, right top, from(#fff), color-stop(100%, rgba(255,255,255,0.1))); 
	position: absolute;
	top: 0;
	left: 50%;
	margin-left: -40px;
	opacity: 0.15;
	height: 80px;
	width: 80px;

/* Colorize them */
	background: #c8171f; 
	background: -moz-radial-gradient(center 45deg,circle cover, #f9d0be, #c8171f);
	background: -webkit-gradient(radial, 40% 40%, 0, 40% 40%, 50, from(#f9d0be), to(#c8171f)); 

	background: #00a1ee; /* Fallback */	
	background: -moz-radial-gradient(center 45deg,circle cover, #cde6f9, #00a1ee);
	background: -webkit-gradient(radial, 40% 40%, 0, 40% 40%, 50, from(#cde6f9), to(#00a1ee)); 

	background: #fcb83d; /* Fallback */	
	background: -moz-radial-gradient(center 45deg,circle cover, #fcf3a6, #fcb83d);
	background: -webkit-gradient(radial, 40% 40%, 0, 40% 40%, 50, from(#fcf3a6), to(#fcb83d)); 

	background: #4d8d00; /* Fallback */
	background: -moz-radial-gradient(center 45deg,circle cover, #d1e5b2, #4d8d00);
	background: -webkit-gradient(radial, 40% 40%, 0, 40% 40%, 50, from(#d1e5b2), to(#4d8d00)); 

Comparison of How Web Browsers Render CSS3

So how does our work look in various browsers? Let’s have a look, shall we?

Mozilla Firefox 3.6

Mozilla Firefox 3.6

Google Chrome 6.0.4

In Google Chrome, you may notice slightly different color tones because of the difference in the way the CSS3 gradients are rendered.

Google Chrome 6.0.4

Safari 5.02

The ornaments in Safari and Chrome are almost identical because they use the same layout engine (WebKit).

Safari 5.02

Opera 10.63

Although Opera browsers support most of the W3C CSS3 specs, the color gradients are missing so they degrade to the solid color we set for the background properties.

Opera 10.63

IE9 Preview

IE9 behaves similarly to Opera, but the latest news regarding this browser is that it will support 2D transformations like WebKit (with its own vendor prefix, -ms-).

IE9 Preview


Even if IE8 has support for pseudo-elements like :before and :after, it totally lacks CSS3 support, so our baubles look like boxes. I included it here just for you to see how our work degrades in browsers that do not have CSS3 support. They look like floppy disks (linked because our younger audience might not know what these ancient devices are), so they might be suitable for a geeky family’s Christmas tree!


IE6 and IE7 couldn’t join our Christmas party for well-known reasons: they lack more than just CSS3 specifications support, but also the :before and :after pseudo-elements; so we would just have four squares with different colors in these two browsers.

I hope you were inspired to learn about CSS3 in this guide and that you have discovered a trick or two that you can use in your projects. I wish you a Merry Christmas and Happy Holidays!

Related Content

About the Author

Catalin Rosu, a.k.a. Red, is a web designer and developer with over 5 years experience in the industry. You can find articles or tutorials on CSS tips and tricks by visiting his blog at You can connect with him on Twitter as @catalinred.

This was published on Dec 21, 2010


Delayed! Dec 21 2010

Brilliant tutorial. Well explained elements which is what we all need now! Thanks!

Simon Willans Dec 21 2010

Awesome tutorial. I think I’m gonna have a play around with this later on.

The comment about the floppy disks made me feel old (I’m only 23 too).

Vivek Parmar Dec 21 2010

thanks for sharing this useful tut, straight away going to make christmas tree.
thanks again

Artful Dodger Dec 21 2010

Wow man! They’re brilliant, thanks!

Jacob Gube Dec 21 2010

@Simon Willans: Haha! that was just a playful, sarcastic joke! Even 14-year-old web developers would know what floppy disks are.

Michael Tuck Dec 21 2010

My middle schoolers have no idea what floppy disks are. Well, most of them.

Excellent article, well explained. It was fun going through this and seeing how it worked.

S. Sahrp Dec 21 2010

And another great tutorial and insight from Catalin – awesome – thank you!

CSS Blog Dec 22 2010

Very nice tutorial Catalin. If you want you can give the baubles some animation. I did something similar, with my Bouncing Navigation. Check it out with Google Chrome or Safari! Have a nice X-Mas!

Jon~301 Dec 22 2010

Awesome !

Thank you all for appreciating this!

Yes, as a further improvement, I agree some webkit animation would do it.

Greg Babula Dec 22 2010

Very cool, what a shame about IE – horrible!

Icechen1 Dec 25 2010

I wonder how it looks like in IE6…

hamim ferdous May 17 2011

amazing! i Can’t believe it!!!

This comment section is closed. Please contact us if you have important new information about this post.