Let’s be honest, dealing with images on the web is kind of a pain. They’re a pain to modify, load slowly and require all sorts of progressive techniques in a responsive environment. But, unfortunately, images are here to stay; there’s no better way to capture a moment in time than with an image. However, we can significantly reduce our use of images by using CSS to recreate elements. But how can we do this while still keeping our designs visually appealing?

With our powers combined

Modern browser technology is our best friend, namely the technology of CSS with its shape rendering capabilities. We can do some crazy stuff with CSS alone! So in this article, we’re going to start simple and see how we can replace common user interface icons with just CSS. No more loading custom icon fonts or exporting PNGs.

Explore CSS Courses

Let’s jump right in

We’re going to go through the creation of 5 fairly standard UI icons:

I’ve chosen these mainly because they can be easily created with little code and with only one element.

A quick note on browser support: anytime I use the border-radius or transform properties, I’m not prefixing them with vendor prefixes, so you may want to add their proper prefixes for wider browser support. Also, all of the examples below work in all modern browsers, including IE9.

Hamburger icon

We see this hamburger-looking icon a lot in mobile navigation patterns. It’s a very simple one to create with CSS, as it’s just 3 rows with some space in between.

The markup for all of these icons will be the same. We’ll use the i element with a reusable icon class and a unique identifier class, like icon_hamburger .

.icon { position: relative; display: inline-block; } .icon::before, .icon::after { content: ""; position: absolute; }

Notice I created rules for the ::before and ::after pseudo-elements and set the content property to an empty string and positioned them absolutely. We’ll be relying heavily on these pseudo-elements to get the job done (hence why we can create these icons with only one HTML element).

For the hamburger icon, we’ll start off by giving .icon_hamburger a width , height and background .



.icon_hamburger { width: 1.625em; height: .313em; background: black; }

Now to add in the top and bottom lines. We’ll use ::before for the top line and ::after for the bottom.



.icon_hamburger::before, .icon_hamburger::after { width: 1.625em; height: .313em; background: black; } .icon_hamburger::before { top: -.625em; } .icon_hamburger::after { bottom: -.625em; }

That’s it! It’s so much easier than an image to maintain, too. Want to change the width? Just modify the pixel value; no Photoshop required! Want to change the color? Easy!

[cta id=”3126″ align=”none”]

Mail icon

The mail icon (envelope) is another item commonly seen in many UIs. To start out, we’ll set the borders to create a rectangle with a triangle notched out of the top. Joel Glovier wrote a great article a while ago on the appendTo blog explaining how CSS triangles work.

.icon_mail { border-top: 1.063em solid transparent; border-right: 1.25em solid black; border-bottom: .5em solid black; border-left: 1.25em solid black; }

Then to create the envelope flap, we’ll use the same technique again to create a triangle with a negative top and left value. The negative top value offsets it from the top just enough to provide the space between the flap and the actual envelope.

.icon_mail::before { top: -1.25em; left: -1.25em; border-top: 1.063em solid black; border-right: 1.25em solid transparent; border-left: 1.25em solid transparent; }

Heart icon

Creating the heart shape involves rotating the pseudo-elements with the transform property, and applying a large border-radius to the top of each tilted rectangle. The main element itself needs no properties at all. First, we’ll create two rectangles out of our ::before and ::after pseudo-elements.

.icon_heart::before, .icon_heart::after { width: 1em; height: 1.563em; background: black; } .icon_heart::after { left: .375em; }

Then we’ll rotate them.



.icon_heart::before, .icon_heart::after { width: 1em; height: 1.563em; background: black; } .icon_heart::before { transform: rotate(135deg); } .icon_heart::after { left: .375em; transform: rotate(45deg); }

And lastly, add a border-bottom-radius to the ::before pseudo-element (because it’s rotated upside down) and a border-top-radius to the ::after .

.icon_heart::before { transform: rotate(135deg); border-bottom-radius: .5em; } .icon_heart::after { left: .375em; transform: rotate(45deg); border-top-radius: .5em; }

Home icon

Creating a home icon starts out by morphing the main element into a triangle.

.icon_home { border-bottom: .938em solid black; border-left: .938em solid transparent; border-right: .938em solid transparent; }

Then we’ll just create two vertical rectangles below the triangle and space them apart to give the impression of a door in the middle.

.icon_home::before { width: .563em; height: .625em; background: black; } .icon_home::before { margin: .938em 0 0 -.688em; } .icon_home::after { margin: .938em 0 0 .125em; }

Camera icon

The camera icon, like the mail icon, starts out as a rectangle with a small border-radius .

.icon_camera { width: 1.938em; height: 1.375em; margin-top: .813em; background: black; border-radius: .125em; }

Then we’ll use the ::before pseudo-element to create a flash on top of the camera, in the shape of a trapezoid. The trapezoid shape is defined similarly to the way we create triangles, except we need to add a width .



.icon_camera::before { height: 0; width: .938em; margin: -.313em 0 0 .313em; border-bottom: .313em solid black; border-left: .188em solid transparent; border-right: .188em solid transparent; }

And finally we’ll add the lens to the front of the camera, using a circle with a border.

Explore CSS Courses

.icon_camera::after { width: .438em; height: .438em; margin: .125em 0 0 .5em; border: .25em solid white; border-radius: .438em; }

Taking it further

As you hopefully saw, creating CSS icons is really not that difficult and doesn’t require a ton of code. I’ve created a CodePen with all of these icons plus a few more. Feel free to play around with it!

Browser support

As mentioned above, all of these examples work in all modern browsers, including IE9. Some of the new CSS3 properties require vendor prefixes, so make sure you use the proper prefixes. In my CodePen, I’m using Compass @includes , which automatically adds in the proper vendor prefixes. If your project requires IE8 support, you unfortunately might want to rethink the use of solely CSS icons, or at least stay away from icons that require border-radius and transform . My suggestion for a fallback would be to use Modernizr to detect which browsers don’t support border-radius and transform , and provide a background image as a fallback.

Explore CSS Courses