Question

Writing an app that uses CSS to define icons, avoiding dependency on external image files. This works fine for circles, squares, triangles, diamonds, which is almost enough.

I wonder if it's possible to create slightly more complex icons like the two grid shaped ones on the right using CSS? It need not support IE8.

CSS icons with a grid shape

.icon {
  height: 20px;
  width: 20px;
  background-color: steelblue;
  display: inline-block;
}
.icon-circle {
  border-radius: 10px;
}
.icon-square {
  border-radius: 0
}
<div class="icon icon-circle"></div>

Was it helpful?

Solution

If you use pseudo elements :before and :after, you can make those icons without images. And you can even make them responsive (see my fiddle).

I used the pseudo elements to create the "white lines" so you will be able to make both last icons like this:

div {
  width: 20%;
  padding-bottom: 20%;
  margin: 5% 10%;
  background-color: #6095C9;
  position: relative;
  float: left;
}
div:after,
div:before {
  content: "";
  position: absolute;
  background-color: #fff;
}
.one:before,
.two:before {
  margin: 0 48%;
  width: 4%;
  height: 100%;
}
.one:after,
.two:after {
  margin: 48% 0;
  height: 4%;
  width: 100%;
}
.two:before {
  height: 50%;
  bottom: 0;
}
<div class="one"></div>
<div class="two"></div>

FIDDLE

OTHER TIPS

Here is another method to achieve the shapes using gradients instead of pseudo-elements. You can play around with the background sizes to produce different effects (like in shape3).

The advantage of this over the pseudo-element method is that it doesn't require any extra real/pseudo-elements but the drawback is that the browser support for linear-gradients is still poor compared to pseudo-elements.

div {
  margin: 10px;
  height: 50px;
  width: 50px;
  background-color: steelblue;
  transition: all 1s;
}
.shape1 {
  background-image: linear-gradient(to top, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px);
  background-size: 100% 50%, 50% 100%;
}
.shape2 {
  background-image: linear-gradient(to top, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px);
  background-size: 100% 50%, 50% 50%, 100%, 100%;
  background-repeat: repeat-y, repeat-x;
}
.shape3{
  background-image: linear-gradient(to top, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px);
  background-size: 100% 50%, 50% 50%, 100%, 100%;
  background-position: 0% 0%, 0% 100%, 0% 0%;
  background-repeat: repeat-y, repeat-x;
}
.shape4 {
  background-image: linear-gradient(to top, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px);
  background-size: 100% 25%, 25% 100%;
  background-position: 0% 100%, 100% 100%;
  background-repeat: repeat-y, repeat-x;
}
.large {
  height: 150px;
  width: 150px;
}

/* Just for demo */

div {
  float: left;
}
.small{
  clear:both;
}
div:hover {
  background-color: crimson;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="shape1 small"></div>
<div class="shape1 large"></div>
<div class="shape2 small"></div>
<div class="shape2 large"></div>
<div class="shape3 small"></div>
<div class="shape3 large"></div>
<div class="shape4 small"></div>
<div class="shape4 large"></div>

You may be able to use a single element here without actually using pseudo elements at all with the help of box-shadow's.

So, say you have a square div element:

div {
  height: 20vw;
  width: 20vw;
  background: tomato;
}
<div></div>


You could then add a box shadow, without a spread, by using:

div {
  height: 20vw;
  width: 20vw;
  background: tomato;
  box-shadow: 21vw 0 tomato;
}
<div></div>


you can even use multiple box shadows by seperating them with a ,:

div {
  height: 20vw;
  width: 20vw;
  background: tomato;
  box-shadow: 21vw 0 tomato, 0 21vw tomato, 21vw 21vw tomato;
}
<div></div>


You would even be able to overlap them:

div {
  height: 20vw;
  width: 20vw;
  background: tomato;
  box-shadow: 21vw 0 tomato, 0vw 21vw tomato, 16vw 21vw tomato, 21vw 21vw tomato;
}
<div></div>


So creating such wouldn't be overly taxing on browser compatibility nor pseudo elements (which could be used for other purposes).

div {
    height:20vw;
    width:20vw;
    background:tomato;
    box-shadow:0 0 0 tomato;
    -webkit-animation: boxshadowmult 8s infinite;
    animation: boxshadowmult 8s infinite;
}
@-webkit-keyframes boxshadowmult {
    0%, 24% {
        box-shadow:0 0 0 tomato;
    }
    25%, 49% {
        height:20vw;
        width:10vw;
        box-shadow:11vw 0 0 tomato;
    }
    50%, 74% {
        height:10vw;
        width:10vw;
        box-shadow:11vw 0 0 tomato, 6vw 11vw 0 tomato, 0 11vw 0 tomato, 11vw 11vw 0 tomato;
    }
    75%, 100% {
        height:10vw;
        width:10vw;
        box-shadow:11vw 0 0 tomato, 0 11vw 0 tomato, 11vw 11vw 0 tomato;
    }
}
@keyframes boxshadowmult {
    0%, 24% {
        box-shadow:0 0 0 tomato;
    }
    25%, 49% {
        height:20vw;
        width:10vw;
        box-shadow:11vw 0 0 tomato;
    }
    50%, 74% {
        height:10vw;
        width:10vw;
        box-shadow:11vw 0 0 tomato, 6vw 11vw 0 tomato, 0 11vw 0 tomato, 11vw 11vw 0 tomato;
    }
    75%, 100% {
        height:10vw;
        width:10vw;
        box-shadow:11vw 0 0 tomato, 0 11vw 0 tomato, 11vw 11vw 0 tomato;
    }
}

/*demo only*/
html{height:100%;
    background: rgb(79,79,79); /* Old browsers */
background: -moz-radial-gradient(center, ellipse cover,  rgba(79,79,79,1) 0%, rgba(34,34,34,1) 100%); /* FF3.6+ */
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(79,79,79,1)), color-stop(100%,rgba(34,34,34,1))); /* Chrome,Safari4+ */
background: -webkit-radial-gradient(center, ellipse cover,  rgba(79,79,79,1) 0%,rgba(34,34,34,1) 100%); /* Chrome10+,Safari5.1+ */
background: -o-radial-gradient(center, ellipse cover,  rgba(79,79,79,1) 0%,rgba(34,34,34,1) 100%); /* Opera 12+ */
background: -ms-radial-gradient(center, ellipse cover,  rgba(79,79,79,1) 0%,rgba(34,34,34,1) 100%); /* IE10+ */
background: radial-gradient(ellipse at center,  rgba(79,79,79,1) 0%,rgba(34,34,34,1) 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#4f4f4f', endColorstr='#222222',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */

}
<div></div>

Using :before and :after, you can create two more "boxes" to play with.

JSFiddle Demo

.icon {
    width: 200px;
    height: 95px;
    background: blue;
}
.triple-square {
    position: relative;
    margin: 0 0 105px 0;
    border-radius: 5px;
}
.triple-square:before {
    content: " ";
    position: absolute;
    bottom: -105px;
    left: 0;
    height: 95px;
    width: 95px;
    background: blue;
    border-radius: 5px;
}
.triple-square:after {
    content: " ";
    position: absolute;
    bottom: -105px;
    right: 0;
    height: 95px;
    width: 95px;
    background: blue;
    border-radius: 5px;
}

Here's another example to create 3 circles in a triangle shape...

http://jsfiddle.net/RrhxN/1/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top