If there’s one thing I love most about what I do it’s building out the challenges that a designer throws my way. There’s almost always a way to reproduce a design in code, and I love figuring out how to get as close to the original design as possible with CSS.
Recently, our creative director here at Sparkbox, Drew, gave me a design to build out for an e-commerce site. There was an element in the site that was sort of a starburst shape that had the price of the product inside. Being that it included a dynamic price, the thing had to grow and adjust appropriately, so I set out to build this thing with CSS.
Dissecting the Design
So here we go. We’ve got a rather pointy circle with the product price inside. (Also notice the subtle inner border Drew’s got going on here. We’ll talk about that a little later.) I took this design and made this:
I know it’s not exactly the same – it has a few less “points” – which I technically could have achieved with a little more markup, but I decided a little less markup and fewer points was worth it. Let’s walk through what’s going on here.
Visualizing What’s Going on Here
Think of this starburst as a series of rotated boxes. The way I wrapped my head around what’s going on here is with a few post-its. Check it:
So I’ve got three elements here, each rotated 30 degrees. (In the finished design I’ll actually have six elements, you’ll see…)
The Markup
<div class="price-container">
<div class="price">
<span class="label">Buy</span>
<span class="number">$15.00</span>
<span class="label">Now</span>
</div>
</div>
I have <div class="price-container">
that, you guessed it, contains the price starburst. I’ll use this for the background of the starburst. The <div class="price">
is the container for the text inside (the price info.) That’s it for the markup. From here, I’ll be styling pseudo classes to create the multiple points. Also, I mentioned earlier that there were a few less points in the CSS version of this starburst. This markup doesn’t really have anything unnecessary in it.
Stylin’ It Up
Now on to the fun part. Let me overview what I’m going to do, then I’ll show you the styles needed to achieve it. I’m going to style .price-container
, .price
, and the :before
and :after
pseudo elements for each. Essentially, I’ve got six elements to work with. I created this background image to apply to each of the elements and I will rotate 15 degrees each:
If you look back at the post its picture above, notice how I drew on the inner border with pencil. Disassembling the post its model gave me one piece that looks like this.
So here are the styles of each element (the comments should help you understand what’s going on here. I also have some notes below.)
.price-container,
.price-container:before,
.price-container:after,
.price-container .price,
.price-container .price:before,
.price-container .price:after {
height: 8.5em;
width: 8.5em;
background: #760B1F url(price-bg.png) top left no-repeat;
background-size: 8.5em;
}
.price-container:before,
.price-container:after,
.price-container .price:before,
.price-container .price:after {
content: "";
position: absolute;
}
.price-container {
margin: 100px auto; /* Centering for demo */
position: relative; /* Context */
top: 2.5em;
left: 2.5em;
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
-o-transform: rotate(-45deg);
transform: rotate(-45deg);
}
.price-container:before {
top: 0;
left: 0;
-webkit-transform: rotate(-30deg);
-moz-transform: rotate(-30deg);
-ms-transform: rotate(-30deg);
-o-transform: rotate(-30deg);
transform: rotate(-30deg);
}
.price-container:after {
top: 0;
left: 0;
-webkit-transform: rotate(-15deg);
-moz-transform: rotate(-15deg);
-ms-transform: rotate(-15deg);
-o-transform: rotate(-15deg);
transform: rotate(-15deg);
}
.price-container .price {
padding: .5em 0em;
height: 7.5em; /* height minus padding */
position: absolute;
bottom: 0;
right: 0;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
z-index: 1; /* important so the text shows up */
}
.price-container .price:before {
top: 0;
left: 0;
-webkit-transform: rotate(60deg);
-moz-transform: rotate(60deg);
-ms-transform: rotate(60deg);
-o-transform: rotate(60deg);
transform: rotate(60deg);
}
.price-container .price:after {
top: 0;
left: 0;
-webkit-transform: rotate(75deg);
-moz-transform: rotate(75deg);
-ms-transform: rotate(75deg);
-o-transform: rotate(75deg);
transform: rotate(75deg);
}
A few things I’ll point out about the styles:
- Notice the order of the rotation angles: This order is important because there is going to be text inside the inner-most element. Therefore, the last element (the one the text going in, in this case
.price
) has to be straight. Notice that.price-container
is rotated -45 degrees and.price
is rotated 45 degrees – back to 0. - The height and width: The height and width has to be set since we are dealing with background images here. I’ve set it in ems to adjust appropriately when the text size increases.
- There’s a padding top and bottom on
.price-container .price
. That’s why the height is a little different than all the others. - Everything is positioned absolutely inside the first container.
.price-container
hasleft: 2.5em
andtop: 2.5em
just to move the whole thing a little. When everything is rotated, the corners go of the page and out of the container a little. - z-index: There’s a
z-index
defined for.price-container .price
. This is so the price information inside this div is visible.
Now all that’s left is styling the text.
.price-container .price span {
position: relative;
z-index: 100;
display: block;
text-align: center;
color: #FE3D5C;
font: 1.8em/1.4em Sans-Serif;
text-transform: uppercase;
}
.price-container .price span.number {
font-weight: bold;
font-size: 2.5em;
line-height: .9em;
color: #fff;
}
Doing It Image-Free
Now, I have some extra stuff in here because the design called for this very subtle inner border. If you don’t like or need the inner border, just remove the bit about background image and background size and design will hold up fine.
Browser Support
This works as-is in IE 9+, Firefox 4.0+, Safari 4.1+ and Chrome 3.0+. IE 8 and below do not support background-size, and Chrome 1.0, Firefox 3.6 and Safari 3.0 will require some vendor prefixes. IE8 does support pseudo elements, however doesn’t support transform
.
The fallback would be a colored square. Very likely not a huge problem.
There You Have It
It’s a price star thing. Flexible enough to grow when you increase your font size. Made with some CSS.
This is really cool that you can make all this with CSS.
But since you need the main picture (Square) to get it started. Wouldn’t it be easier to just take the starburst image he gave you and use it as a background?
And If you wanted to make it so you can edit the text inside just clone stamp the original text out and then position text inside.
To me this seems easier :P.
Anywho this is an amazing coding job, well done.
Yeah, but then there would be hardly anything in the way of CSS or tricks to it, now would there? :p
Go to the demo page and try to change the size of the text. See the drawing changing accordingly? It makes the point!
Very creative, and great execution. I make images for badges similar to this one all the time—but the more we can switch from images to fully CSS solutions the better. The border is also a nice touch. Thanks for the write-up!
Yes, this is brilliant :)
Nice example on the power of css3, but I have to agree with Zach, this excercise is totally pointless as you have to use an image to start with.
Why wouldn’t you use the star as the background image with your text over layed in the div, saving you a heap of time as you wouldn’t have to code an extra 100 lines of css, with a result that would work on ALL web browsers instead of 4?
This is brilliant. I can’t wait to try it. It’s great, from a Page load speed perspective, to use CSS rather than images.
Gary,
He’s still using an image… Page load wouldn’t change if he simply used the entire image of the star rather than just a border-outline of it. Other commenters have it right — this exercise is great for the brain, but not so much for functionality.
Awesome tutorial. It impressive the things that can be done with CSS alone.
But (there is always a ‘but’, isn’t it?) I don’t think this example is very practical since you have to create an image anyway, why don’t create the starburst as a background and reduce the CSS greatly?
Nice tutorial, kind of have to agree with Zach, since you’re using an image anyways wouldn’t it be easier to use the whole image and do `background-size: 100% 100%` so it always stretches both horizontally and vertically?
Don’t forget, this all can be done completely image-free. In this particular case, the design called for an inner border, so the image solution worked best. Removing the background-image and using a background-color will give the same result – and in that case much more flexible than using a starburst image.
Using CSS alone , this is mind blowing stuff ,a few years ago this would have blown minds of any CSS expert, this just shows how much CSS has evolved, maybe in the future we might see complex patterns integrated into CSS or maybe all the Flash like effects or maybe who knows what………..
Have a look at the recently drafted CSS shaders!
Mind = blown
Amazingly Awesome
Hm, what about using
border-radius
w/border-image
? Didn’t sure, is that works in that mix, but it should, i guess.Same as the others, a solution totally image free would have been really great.
Oh, and you forgot to mention Opera in the browser support ;)
Very good.
Good work! Now, having this get out of the way… :)
Let’s forget about images for a second. Not that images are wrong. Images will outlive CSS3, I have no doubts.
I don’t see here nothing you can’t do better with SVG and get more browser coverage in the process.
Although it can be done with CSS, I personally think, *again* ;), that CSS it’s really not the right tool for the job here.
As a CSS exercise, as a CSS challenge, no doubt, this one has its merits. The final product however fails to deliver the overall graphic quality one’s expecting.
And that’s the essential part right here! Not many will appreciate the coding technique, but all will judge the final graphic quality.
As such, if not an image, then certainly a SVG would be more appropriate for this type of thing.
I guess what I’m saying is connected with my previous comments: the difficult part is to decide when some CSS Tricks can go beyond being smart concepts and prove themselves worthy of use in real projects.
The ‘Visualizing What’s Going on Here’ was essential! nice analogy.
Chris,
While this is a very genus usage of new concepts of CSS3 (transform => rotate), but I checked out the end result alongside your code. It doesn’t scale out if you increase the digits of the price. For example, if you change 39 to 3999, then a digit falls out of the circle.
If this is the case, then why not using a simple background image?
Nice brilliant idea!!!
A stolen idea passed off as your own, well done.
http://matthewjamestaylor.com/blog/css3-starbursts
Matthew,
How is this stolen? This tutorial uses a completely different process than what is shown in the article link you shared.
The titles are similar, but that’s about it.
I’m too lazy to do it, but I’m sure we can find other articles with methods for creating CSS-based starbursts older than the Matthew article. Just because you aren’t the first to document a method doesn’t mean you stole anything.
Here’s an idea. Update your article with a link to Chris’ post, and put a link to your post in the comments to this post. Think about what benefits the community. If you are writing articles just for yourself then password protect your blog so no one can ‘steal’ the contents.
Hmmm, let me step up in Matt’s defense. I’ve used (and modified, and sometimes abused) his layouts and nav menus in several projects, and asked him for advice on their use a time or two, with friendly and useful responses. He’s made a ton lot of extraordinarily well done materials that are all free for the download, with only a generic “donate if you wish” request attached.
So to lay into him with an admonishment to privacy-protect his blog so no one can “steal” his materials is bullsh_t pure and simple. He and Chris both make a tremendous amount of materials available for the taking, both doing so from what I believe to be a sincere love of design/development and a spirit of generosity and “giving back to the community.”
For the starburst, Chris’s methodology is quite different from Matt’s. However, the concepts are similar enough to say that Chris should have acknowledged Matt’s work — had he known about it, which he may well have not — in the post. Matt probably could have used a less loaded word than “stolen,” because Chris didn’t steal Matt’s work.
That ought to settle the issue. Stand down, folks.
This is the real Matthew James Taylor here…
I’d just like to point out that the ‘stolen’ comment above was not by me. It was by added by some someone pretending to be me. It’s a shame that people can pass off as someone else and make people look bad.
Chris, is there any way we can change his comment so it doesn’t look like it’s from me? BTW I am actually a big fan of your work and dedication, I’m way to lazy to be a prolific as you! ;)
No prob. Cheers.
Haha, awesome idea to draw it on a couple of rectangled pieces of paper first!
This is damn awesome! I can’t believe guys like Ryan Buttrey exist.
Seriously, you guys keep coming up with innovative CSS stuff. No-one can call CSS an easy or basic language to learn. CSS deserves to be mastered as much as PHP, ASP.NET, C++ or Assembly.
Crazy, although I’d just use an image cuz Im lazy:)
Very creative, like it :)
I love finding random cool stuff, especially if it is CSS related so this fits the ticket nicely.
Thanks for sharing your ideas, now I am off to throw in some funky on hover rotation and colour change into the mix .
Simon
K2Joom.com
This is so rad. I wonder if there is a way to add CSS gradients into the mix.
You should be able to do even the inner border version image free for modern browsers if you add some unsemantic markup. Say two div containers with class names innerborder-1& innerborder-2 which together with their pseudo elements are six absolutely positioned blocks with transparant bg and light brown border. Then let one of the spans be a circle block with brown bg to cover up the borders inside the inner star.
You can always debate if saving one http request is worth having that extra markup and the need for a css2 fallback, but I’m not sure it wouldn’t!
Fun post, I particularly like the visualize with postits concept!
TooFrigginCool.
I’m not sure if I’d ever use it, as starbursts are a bit cliché, but I love reading articles like this purely from ‘coding fun’ standpoint. Kudos, Chris – a very enlightening read.
All I can say is that is simply awesome…
Hey everybody, I’ve noticed several people both praising and criticizing Chris for this post. Just thought I’d mention that Chris didn’t write it. It is a guest post by Ryan Buttrey.
Why???
Pure curiosity, to prove it can be done, to experiment, for good old fashioned fun, to provide a challenge, to push the coding envelope, etc. etc. etc. But that is just my guess.
You’re crazy haha (in a good way, of course) – you must have so much fun making this stuff. Even if something isn’t practical to build out with css (and said tricks) yet, it’s still interesting to see how you get it done. Funny to me when people miss this point in some of your posts. Anyways, this is really cool. Good work!
Great offer,
can i use it for my joomla website?
this seems another mis-use of css. i think we have to keep in mind that css should not be used to originate content; rather to style it. otherwise this is a very contrived example of “clever” css coding. i’d rather see some more good and appropriate use of css2 and css3..perhaps in concert with svg, to keep things exciting without inventing and reinforcing bad coding. there’s also stuff to talk about xslt & css etc.
i’d like to see more real/useful code, like in the old days of css-tricks. otherwise my patronage to this website is in a steep decline.