How to create CSS Icons

In the sites and articles referenced below, simple, standard CSS is used to form beautiful icons. However, I have yet to find any advice on how to prepare your own and in this article I aim to redress the issue, and set you on your way.

Introduction

I find it is amazing what can be achieved using simple and regular CSS to create artistic and informative iconography. It is almost an art-form in its own right.

This article was inspired by the wonderful Icono (http://saeedalipoor.github.io/icono/) site by Saeed Alipoor (https://github.com/saeedalipoor)

and

Licon (http://siamak.github.io/licon/) by Siamak Mokhtari (http://siamak.us/).

In my very personal opinion, all CSS articles like this should make reference to one or more articles at CSS-TRICKS and, where appropriate, demonstrations a CodePen. Chris Coyier & co. have compiled excellent repositories of CSS wisdom. In this case have a very useful article called The Shapes of CSS(https://css-tricks.com/the-shapes-of-css/), demonstrated as an interactive gallery(https://css-tricks.com/examples/ShapesOfCSS/). The page is ‘interactive’ in that you can edit the code snippets directly and see the result of the change immediately.

Please see the list at the end of this article acknowledging the contributors to the gallery. On CodePen, Ricardo Zea (http://ricardozea.design/) has compiled some basic examples (http://codepen.io/ricardozea/pen/vqckl) using the SASS CSS pre-processor.

Starting simple

We need a container for our icon that can be used anywhere in our web page. We could use a generic tag such as a div, a span or even a list il but both of the example cited above attempt to reuse the <i> tag. This is not without controversy as the <i> tag has a distinct semantic purpose and “defines a part of text in an alternate voice or mood” (http://www.w3schools.com/tags/tag_i.asp).

However, I think such styling should be the preserve of CSS, so I have no issue “hijacking” the <i> tag to mean icon. We will also be adopting the convention of using CSS classes rather than Ids to apply the styling.

<i class=’iDisc’></i>   rather than   <i id=’iDisc’></i>.

One thing Microsoft did right with CSS in IE was their implementation of the box model. According to the specification the width and height should include not just the content of the element but the padding and border as well. Just because all the other browser implementers chose a different interpretation to implement, does not make theirs right. But, to appease everyone we now have the box-sizing style. We want all of our icon to appear within a clearly defined area so we shall be using the border-box mode.

To make things visible we will apply a common style to all i tags.

i {

box-sizing: border-box;

display: inline-block;

position: relative;

width: 0;
height: 0;

}

i:before, i:after {

position: absolute;
content: “”;

pointer-events: none;
width: 0;
height: 0;

}

So, let us start with a rectangle.

.iRectangle {

width: 100px;
height: 100px;
background-color: red;

border: 10px solid #000;

}

What is displayed is actually a square but that is just a matter of selecting appropriate dimensions. But how about ‘wonkey’ sides.

.iTrapezoid {
width: 100px;
border-bottom: 100px solid orange;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
}

Going round

Let’s round off some corners – nothing miraculous about that.

.iRectangleRounded {

width: 100px;
height: 100px;
background-color: red;

border: 10px solid #000;

border-radius: 10% 20% 30% 40%;

}

Each corner running clockwise from the top-left corner has an increasingly larger radius of curve, all proportional to the size of the icon. From this it is simple to see how we can make a circle, an oval or even an egg shape.

.iOval {

width: 200px;
height: 100px;
background-color: orange;

border: 10px solid #000;

border-radius: 50%;

}

This alright for horizontal or vertically aligned ovals but what about diagonally arranged ovals: Transforms.

.iDiagOval {

width: 200px;
height: 100px;

background-color: yellow;

border: 10px solid #000;

border-radius: 50%;

transform: rotate(45deg);

}

.iEgg {

width: 140px;

height: 200px;

background-color: green;

border: 5px solid #000;

border-radius: 50%  50%  50%  50%  / 60%   60%   40%  40%;

}

Triangles

In graphics the triangle is regarded as one of the most versatile shapes for a variety of reasons. On the web one of the most common uses of triangles is arrow heads, so how can we manage that. Well, there are two basic forms we will consider; diagonal and lateral (horizontal/vertical.)

.iTriangleTopLeft {

border-top: 100px solid green;
border-right: 100px solid transparent;

}

To change the direction we only need to select different adjacent side to show/hide. We do not have to rotate the object. One thing to notice: We are now using the border to form the shape so we cannot have (at this point) a border around it.

.iTriangleRight {

border-top: 50px solid transparent;
border-left: 100px solid cyan;
border-bottom: 50px solid transparent;

}

The lateral triangles use three sides (2 hidden and 1 visible) but none of them being the direct we want to triangle to point. Again, the other directions just employ different combination of borders.

Seeing stars

We can bring together a number of triangles to form stars using the pseudo elements, :before and :after.

The hexagram (6-pointed star)

.i6Star {
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid blue;
}
.i6Star:after {
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-top: 100px solid magenta;
top: 30px;
left: -50px;
}

The pentagram (5-pointed star)

Special thanks to Kit MacAllister.

.i5Star {
border-right:  100px solid transparent;
border-bottom: 70px  solid red;
border-left:   100px solid transparent;
transform:    rotate(35deg);
}
.i5Star:before {
border-bottom: 80px solid green;
border-left: 30px solid transparent;
border-right: 30px solid transparent;
top: -45px;
left: -65px;
transform: rotate(-35deg);
}
.i5Star:after {
top: 5px;
left: -108px;
border-right: 100px solid transparent;
border-bottom: 70px solid blue;
border-left: 100px solid transparent;
transform: rotate(-70deg);
}

See the last section on how I created a version of the i5Star (iPentacle) based on repeating and rotating an isosceles triangle.

A 12-point burst

Acknowledgment to Alan Johnson

.i12Burst {
background-color: red;
width: 100px;
height: 100px;
}
.i12Burst:before,

.i12Burst:after {
height: 100%;
width: 100%;
background-color: red;
transform: rotate(30deg);
}
.i12Burst:after {
transform: rotate(60deg);
}

Time to get fancy

We have seen how we can use border transparency and radius to make basic shapes. We have used the before and after pseudo elements to compose more complex shapes from basic shapes but it does not stop there. Notice how the point of rotation (transform-origin) is offset.

.iHeart {
width: 100px;
height: 100px;
}
.iHeart:before,
.iHeart:after {
left: 50px;
top: 0;
width: 50px;
height: 80px;
background-color: red;
border-radius: 50% 50% 0 0;
transform: rotate(-46deg);
transform-origin: 0 100%;
}
.iHeart:after {
left: 0;
transform: rotate(46deg);
transform-origin: 100% 100%;
}

Special thanks to Nicolas Gallagher for this beautiful heart (above) and Alexander Futekov for the Yin-Yang (below).

.iYinYang {

width: 100px;

height: 100px;

background: #eee;

border-color: #000;

border-style: solid;

border-width: 2px 2px 50px 2px;

border-radius: 100%;

}

.iYinYang:before,

.iYinYang:after {

top: 50%;

width: 12%;

height: 24%;

border: 18px solid #000;

border-radius: 100%;

}

.iYinYang:before {

left: 0;

background: #eee;

}

.iYinYang:after {

left: 50%;

background: #000;

border-color: #eee;

}

But there is more

There is another style “box-shadow” we can use to add another level of detail. To demonstrate it I will use this simple little example from Omid Rasouli (thank you.)

.iCrescentMoon {
width: 100px;
height: 100px;
border-radius: 50%;
box-shadow: 15px 15px 0 0 red;
}

An to the other extreme we have this Space Invader thanks to Vlad Zinculescu. Notice how box-shadow is being used repeatedly to produce a pixel-art effect.

.iSpaceInvader{

width: 1em;

height: 1em;

box-shadow:

0 0 0 1em red,

0 1em 0 1em red,

-2.5em 1.5em 0 .5em red,

2.5em 1.5em 0 .5em red,

-3em -3em 0 0 red,

3em -3em 0 0 red,

-2em -2em 0 0 red,

2em -2em 0 0 red,

-3em -1em 0 0 red,

-2em -1em 0 0 red,

2em -1em 0 0 red,

3em -1em 0 0 red,

-4em 0 0 0 red,

-3em 0 0 0 red,

3em 0 0 0 red,

4em 0 0 0 red,

-5em 1em 0 0 red,

-4em 1em 0 0 red,

4em 1em 0 0 red,

5em 1em 0 0 red,

-5em 2em 0 0 red,

5em 2em 0 0 red,

-5em 3em 0 0 red,

-3em 3em 0 0 red,

3em 3em 0 0 red,

5em 3em 0 0 red,

-2em 4em 0 0 red,

-1em 4em 0 0 red,

1em 4em 0 0 red,

2em 4em 0 0 red;

background: red;

margin: 0 0 0 8%;

}

If pixel-art is form you find particularly pleasing, you might want to check out another CSS-Tricks article “Fun Times With CSS Pixel Art” (https://css-tricks.com/fun-times-css-pixel-art/) by Geoff Graham. Here is an on-line editor (http://pixelart.jvrpath.com/) should you want to experiment with creating CSS pixel-art.

Hopefully by now you can see how, through a combinations of the techniques discussed above, we can construct a wide variety of CSS-only icons; one way or another.

A Worked Example – “Picking up the Slack”

In Saeed Alipoor’s collection of CSS icons there are a number of examples where a company logo has been produced using the technique. In this step-by-step example I have chosen to try and duplicate the gate emblem of the Slack logo (https://slack.com/) in inverted colours. Rather than provide figures at each step I suggest you copy and paste or retype the code in a CodePen session of your own.

  1. Start with a simple back rectangle (square)

.iSlack {

width: 100px;

height: 100px;

background: #000;

}

  1. We round off the corners with border-radius at 40%

.iSlack {

width: 100px;

height: 100px;

background: #000;

border-radius: 40%;

}

  1. Give it a little tilt by adding a -20 degree rotation transform

.iSlack {

width: 100px;

height: 100px;

background: #000;

border-radius: 40%;

transform: rotate(-20deg);
}

  1. Add a tilted horizontal using the :before pseudo element

.iSlack:before {

width: 60px;

height: 10px;

background: #fff;

left: 20px;

top: 32px;

}

  1. And another using box-shadow

.iSlack:before {

width: 60px;

height: 10px;

background: #fff;

left: 20px;

top: 32px;

box-shadow: 0 24px 0 0 #fff;

}

  1. Finally we add the vertical lines

.iSlack:after {

width: 10px;

height: 60px;

background: #fff;

left: 32px;

top: 20px;

box-shadow: 24px 0 0 0 #fff;

}

Ok, so it might not be a faithful reproduction but I hope you can see the effect I was after.

Some quick disclaimers

  1. I have removed some style duplication resulting from venda prefixing such as
    -webkit-transform: rotate(-45deg); a CSS pre-processor will help such matters.
  2. Most modern browsers support percentages for border-radius but not all. So, you may have to calculate the actual pixels as a proportion of the size of the icon, which is a little inflexible.
  3. Without evidence to support the statement, indications are that CSS shapes (icons) might exhibit rather poor performance. Using half a dozen should not pose too much of an issue but if you are considering using dozens you might want to conduct some performance tests before committing your project.
  4. On Microsoft IE I have observed that some of the edges don’t quite align creating gets between elements of the icon.

I have captured the examples demonstrated above in the CodePen at http://codepen.io/TracyGJG/pen/XNEwmp.

Shapes of CSS gallery contributor acknowledgement

Alan Johnson (http://commondream.net/post/8848553728/pure-css-badges)

Alexander Futekov (http://www.futekov.com/alexander/)

Ando Razafimandimby (http://about.me/fwd)

Anthony Ticknor (http://twitter.com/apticknor)

Catalin Rosu (http://www.red-team-design.com/)

Joseph Silber (https://josephsilber.com/index.php/posts)

Josh Rodgers (http://joshrodgers.com/)

Kaya Basharan (https://css-tricks.com/examples/ShapesOfCSS/#)

Kit MacAllister (http://kitmacallister.com/2011/css-only-5-point-star/)

Nathan Swartz (http://clicknathan.com/)

Nicolas Gallagher (http://nicolasgallagher.com/)

Omid Rasouli (http://www.blendesign.ir/)

Vlad Zinculescu (http://ecsspert.com/)

Zoe Rooney (http://codepen.io/zoerooney/pen/xIoCn)

Creating a pentacle (iPentacle) using three rotated isosceles triangles

The 5-pointed star designed by Kit MacAllister (i5Star) works just fine but it does not employ a consistent approach, which makes it more difficult to adapt than needs be. My approach (iPentacle) uses 3 identical isosceles triangles (tall thin arrow heads) rotated 18, 72 and 144 degrees respectively, along with some repositioning.

  1. We start with a known width of the pentacle (200px) that defines the height of a rectangle that bounds a right-pointing arrow head. The top and bottom angles are each equal one fifth of 180 (36) degrees. This leaves an angle of three-fifths of 180 (108) degrees for the point of the arrow, which peaks at 72.65px to give us the width of the rectangle.
  2. The actual width and height of the rectangle are zero but with the box-sizing set to border-box we use the borders to create the triangle. We start by setting the top and bottom border width to 100px (both transparent) and set the left border to the desired width (72.65px) in our chosen colour. This is the same for all three triangles we will be using to form the pentacle as iPentacle, iPentacle:before and iPentacle.after.
  3. For the purpose of the exercise it is worth using three different colours and setting the opacity to 0.7 (70%) to allow the composition to be apparent. The angles of rotation will mean two point will overlap.
  4. The base shape (iPentacle) needs to be offset right by 70px using margin-left because its positioning is relative. The :before and :after components are absolute (relative to the base shape) positioned so can use negative top and left values to pull the shape into position overlapping each other. The exact values need manual fine adjustment but in this case result as follows:
:before :after
top -98px -96px
left -79px -75px

‘That’s all folks’ as the old cartoons used to end. We have a pentacle (5-pointed star) by overlaying three isosceles triangles, each rotated and repositioned.