Create a lightning bolt design (like The Flash)

Solution 1:

SVG

Here you go @Professor.CSS. @jbutler483
A Circle
And Polygon

svg {
  background-color: red;
}
<svg width="100px" height="200px" viewBox="0 0 100 150">
  <circle fill="white" stroke="black" cx="50" cy="75" r="50"></circle>
  <polygon stroke="gray" fill="yellow" points="100,0 67,50 90,45 47,100 70,95 0,150 27,110 12,113 50,70 30,73 100,0" />
</svg>

or css

Its just ::before and ::after elements on the lighting. drop-shadow on the lighting container.

body {
  background-color: red;
}
.container {
  -webkit-filter: drop-shadow(2px 2px 0px gray);
}
.circle {
  display: inline-block;
  border-radius: 50%;
  background-color: white;
  border: 5px solid black;
  border-color: black;
}
.lightning {
  position: relative;
  margin: 50px;
  width: 30px;
  height: 50px;
  transform-origin: 50% 50%;
  transform: skewX(-30deg) skewY(-30deg) rotate(10deg);
  background-color: yellow;
}
.lightning:before {
  position: absolute;
  border-style: solid;
  border-width: 0 0 40px 30px;
  border-color: transparent transparent yellow transparent;
  top: -39px;
  left: -17px;
  content: "";
}
.lightning:after {
  position: absolute;
  border-style: solid;
  border-width: 0 0 40px 30px;
  border-color: transparent transparent transparent yellow;
  bottom: -39px;
  right: -17px;
  content: "";
}
<div class="circle">
  <div class="container">
    <div class="lightning"></div>
  </div>
</div>

Solution 2:

Disclaimer: Use SVG for complex images. We can still have some fun with CSS, though, just use this for learning and not production implementation.

Is this possible with a single HTML element?

Yeah! ... with limitations — mainly no border on the bolt... but, hey, minimal HTML!

  • The top and bottom sections are created with the transparent border triangle trick on :before and :after
  • The middle bolt is created with the box-shadow of :before

Very rough example

Note: This example uses a <div>, as it requires pseudo-element children.

body {
  background: #F00;
}
div {
  height: 300px;
  width: 300px;
  background: #FFF;
  border-radius: 50%;
  border: solid 5px #000;
  margin-top: 200px;
  position: relative;
}
div:before,
div:after {
  content: '';
  position: absolute;
  transform: skewY(-30deg) rotate(20deg);
}
div:before {
  border-right: solid 70px yellow;
  border-top: solid 160px transparent;
  box-shadow: 50px 100px yellow;
  left: 50%;
  margin-left: -50px;
  top: -70px;
}
div:after {
  border-right: solid 70px transparent;
  border-top: solid 160px yellow;
  bottom: -30px;
  left: 100px;
}
<div></div>

Solution 3:

Disclaimer: I recommend SVG for these but that doesn't mean we shouldn't be having fun with CSS. Use this for learning but not production implementation.

Here is a method to achieve the shape with just a single element (+ a couple of pseudos) and some background linear-gradients. The shape can be scaled without any distortions.

Explanation on how the shape was achieved:

  • The white circle with the black border is a normal CSS circle created using border-radius on a pseudo-element (:after).
  • Another pseudo-element (:before) is added and is skewed along both X and Y axes to give the bolt's parts a skewed appearance.
  • The bolt is actually created by stacking multiple linear-gradients on top of one another. It involves 6 gradient images where 3 are for the inside yellow part of the bolt and the other 3 are for the gray borders.
  • The size of the background images (gradients) are determined by the size of the bolt and each of them is positioned in such a way that they produce the lightning bolt like appearance.
  • The center part of the bolt actually has only one solid color but is still produced using a gradient because we can't control the size of solid color backgrounds.

Note: Scaling works pretty well if transform: scale(...) is used instead of a height/width change + transition.

.lightning {
  position: relative;
  height: 200px;
  width: 200px;
  border-radius: 50%;
  margin: 50px auto;
}
.lightning:after,
.lightning:before {
  position: absolute;
  content: '';
  height: 100%;
  width: 100%;
  top: 0%;
  left: 0%;
}
.lightning:after {
  background: white;
  border: 2px solid;
  border-radius: 50%;
  z-index: -1;
}
.lightning:before {
  background: linear-gradient(transparent 0%, yellow 0%), linear-gradient(to top left, yellow 43%, gray 43%, gray 44%, transparent 44%), linear-gradient(to top left, transparent 56%, gray 56%, gray 57%, yellow 57%), linear-gradient(transparent 0%, gray 0%), linear-gradient(to top left, gray 51%, transparent 51%), linear-gradient(to top left, transparent 49%, gray 49%);
  background-size: 20% 40%, 22% 42%, 22% 42%, 23% 42%, 23% 42%, 23% 42%;
  background-position: 50% 50%, 32% 5%, 70% 100%, 50% 50%, 33% 7%, 69% 98%;
  background-repeat: no-repeat;
  backface-visibility: hidden;
  transform: skewY(-30deg) skewX(-30deg);
  z-index: 2;
}

/* Just for demo */

body {
  background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
.lightning {
  transition: all 1s;
}
.lightning:hover {
  transform: scale(1.5);
}
<!-- Script used only for avoidance of prefixes -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>

<div class="lightning"></div>

With Animation for Bolt:

.lightning {
  position: relative;
  height: 200px;
  width: 200px;
  border-radius: 50%;
  margin: 50px auto;
}
.lightning:after, .lightning:before {
  position: absolute;
  content: '';
  height: 100%;
  width: 100%;
  top: 0%;
  left: 0%;
}
.lightning:after {
  background: white;
  border: 2px solid;
  border-radius: 50%;
  z-index: -1;
}
.lightning:before {
  background: linear-gradient(transparent 0%, yellow 0%), linear-gradient(to top left, yellow 43%, gray 43%, gray 44%, transparent 44%), linear-gradient(to top left, transparent 56%, gray 56%, gray 57%, yellow 57%), linear-gradient(transparent 0%, gray 0%), linear-gradient(to top left, gray 51%, transparent 51%), linear-gradient(to top left, transparent 49%, gray 49%);
  background-size: 20% 40%, 22% 42%, 22% 42%, 23% 42%, 23% 42%, 23% 42%;
  background-position: 50% 50%, 32% 5%, 70% 100%, 50% 50%, 33% 7%, 69% 98%;
  background-repeat: no-repeat;
  backface-visibility: hidden;
  transform: skewY(-30deg) skewX(-30deg);
  z-index: 2;
}

/* Just for demo */

body {
  background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
.lightning {
  transition: all 1s;
}
.lightning:hover:before {
  animation: boltstrike 1s;
}
@-webkit-keyframes boltstrike {
  25% {
    transform: translateX(-5%) translateY(5%) skewY(-30deg) skewX(-30deg);
  }
  50% {
    transform: translateX(7.5%) translateY(-7.5%) skewY(-30deg) skewX(-30deg);
  }
  100% {
    transform: skewY(-30deg) skewX(-30deg);
  }
}
@keyframes boltstrike {
  25% {
    transform: translateX(-5%) translateY(5%) skewY(-30deg) skewX(-30deg);
  }
  50% {
    transform: translateX(5%) translateY(-5%) skewY(-30deg) skewX(-30deg);
  }
  100% {
    transform: skewY(-30deg) skewX(-30deg);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>

<div class="lightning"></div>

Click here for a full demo with animation, color change on click etc.


Older version without border:

.lightning {
  position: relative;
  height: 200px;
  width: 200px;
  border-radius: 50%;
}
.lightning:after,
.lightning:before {
  position: absolute;
  content: '';
  height: 100%;
  width: 100%;
  top: 0%;
  left: 0%;
}
.lightning:after {
  background: white;
  border: 2px solid;
  border-radius: 50%;
  z-index: -1;
}
.lightning:before {
  background: linear-gradient(transparent 0%, yellow 0%), linear-gradient(to top left, yellow 50%, transparent 50%), linear-gradient(to top left, transparent 50%, yellow 50%);
  background-size: 20% 40%, 20% 40%, 20% 40%;
  background-position: 50% 50%, 30% 5%, 70% 100%;
  background-repeat: no-repeat;
  backface-visibility: hidden;
  transform: skewY(-30deg) skewX(-30deg);
  z-index: 2;
}

/* Just for demo */

body {
  background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
.lightning {
  transition: all 1s;
}
.lightning:hover {
  height: 250px;
  width: 250px;
}
<!-- Script used only for avoidance of prefixes -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>

<div class="lightning"></div>

Solution 4:

Managed to complete this using CSS skews and rotates with some positioning.

Its not the cleanest and its also not great for responsiveness or changing the size but it works and its as close as I could get with my short space of time.

Code is below:

#lightning {
  position: relative;
  height: 1000px;
  width: 600px;
  background: red;
}
.above,
.below {
  height: 100%;
  width: 100%;
  position: absolute;
  top: 100px;
}
.above .middle {
  background: yellow;
  position: absolute;
  top: 300px;
  left: 100px;
  height: 125px;
  width: 400px;
  -webkit-transform: rotate(111deg) skew(35deg);
  transform: rotate(111deg) skew(35deg);
}
.above .toptri {
  position: absolute;
  height: 200px;
  width: 0px;
  padding: 0px;
  top: -175px;
  left: 300px;
  -webkit-transform: rotate(0deg) skew(141deg);
  transform: rotate(0deg) skew(141deg);
  border-top: 0px transparent;
  border-left: 50px solid transparent;
  border-right: 128px solid transparent;
  border-bottom: 284px solid #FFFF00;
  -webkit-transform: rotate(350deg) skew(141deg);
  transform: rotate(350deg) skew(141deg);
}
.above .bottri {
  position: absolute;
  height: 200px;
  width: 0px;
  padding: 0px;
  top: 400px;
  left: 125px;
  -webkit-transform: rotate(0deg) skew(141deg);
  transform: rotate(0deg) skew(141deg);
  border-top: 0px transparent;
  border-left: 50px solid transparent;
  border-right: 128px solid transparent;
  border-bottom: 284px solid #FFFF00;
  -webkit-transform: rotate(170deg) skew(141deg);
  transform: rotate(170deg) skew(141deg);
}
.below .middle {
  background: grey;
  position: absolute;
  top: 280px;
  left: 80px;
  height: 165px;
  width: 440px;
  -webkit-transform: rotate(111deg) skew(35deg);
  transform: rotate(111deg) skew(35deg);
}
.below .toptri {
  position: absolute;
  height: 160px;
  width: 0px;
  padding: 0px;
  top: -200px;
  left: 265px;
  -webkit-transform: rotate(0deg) skew(141deg);
  transform: rotate(0deg) skew(141deg);
  border-top: 0px transparent;
  border-left: 80px solid transparent;
  border-right: 158px solid transparent;
  border-bottom: 370px solid grey;
  -webkit-transform: rotate(350deg) skew(141deg);
  transform: rotate(350deg) skew(141deg);
}
.below .bottri {
  position: absolute;
  height: 200px;
  width: 0px;
  padding: 0px;
  top: 400px;
  left: 125px;
  -webkit-transform: rotate(0deg) skew(141deg);
  transform: rotate(0deg) skew(141deg);
  border-top: 0px transparent;
  border-left: 50px solid transparent;
  border-right: 128px solid transparent;
  border-bottom: 284px solid #FFFF00;
  -webkit-transform: rotate(170deg) skew(141deg);
  transform: rotate(170deg) skew(141deg);
}
.below .bottri {
  position: absolute;
  height: 160px;
  width: 0px;
  padding: 0px;
  top: 380px;
  left: 100px;
  -webkit-transform: rotate(0deg) skew(141deg);
  transform: rotate(0deg) skew(141deg);
  border-top: 0px transparent;
  border-left: 80px solid transparent;
  border-right: 158px solid transparent;
  border-bottom: 370px solid grey;
  -webkit-transform: rotate(170deg) skew(141deg);
  transform: rotate(170deg) skew(141deg);
}
<div id="lightning">
  <div class="below">
    <div class="toptri"></div>
    <div class="middle"></div>
    <div class="bottri"></div>
  </div>
  <div class="above">
    <div class="toptri"></div>
    <div class="middle"></div>
    <div class="bottri"></div>
  </div>
</div>

CodePen

Solution 5:

CSS

CSS only using :before and :after pseudo elements, CSS triangles and transform. It would be difficult to make this particular solution responsive given the usage of CSS triangles as borders cannot be percentage based. This solution uses two divs as the basis of the lightning bolt and it's outline.

The bolt is created in the following way:

  • The middle of the bolt is specified in .boltOuter/.boltInner. It is a rectangle skewed on the X and Y axis to make it a tilted rhombus
  • The "prongs" are the :before and :after pseudo elements positioned relatively to the container .boltOuter/.boltInner
  • The "prongs" are made using CSS triangles (zero height and width elements with selective borders). The triangles are rotated to get the desired angle
  • All elements of .boltInner are made smaller and offset from .boltOuter to allow .boltOuter to act as the silver outline

body {
    background-color: red;
}
.circle {
    background-color: white;
    border: 5px solid black;
    border-radius: 50%;
    height: 400px;
    left: 100px;
    position: relative;
    top: 200px;
    width: 400px;
}
.boltOuter, .boltInner {
    position: absolute;
}
.boltOuter:before, .boltOuter:after, .boltInner:before, .boltInner:after {
    content: "";
    display: block;
    height: 0;
    position: absolute;
    transform: rotateY(-60deg);
    width: 0;
}
.boltOuter {
    background-color: silver;
    height: 300px;
    left: 140px;
    top: 50px;
    transform: skewX(-10deg) skewY(-20deg);
    width: 110px;
    z-index: 2;
}
.boltOuter:before, .boltOuter:after {
    border: 150px solid transparent;
    z-index: 1;
}
.boltOuter:before {
    border-bottom-color: silver;
    border-right-color: silver;
    left: -150px;
    top: -200px;
}
.boltOuter:after {
    border-left-color: silver;
    border-top-color: silver;
    bottom: -200px;
    right: -150px;
}
.boltInner {
    background-color: gold;
    height: 290px;
    left: 5px;
    top: 5px;
    width: 100px;
    z-index: 4;
}
.boltInner:before, .boltInner:after {
    border: 140px solid transparent;
    z-index: 3;
}
.boltInner:before {
    border-bottom-color: gold;
    border-right-color: gold;
    left: -143px;
    top: -190px;
}
.boltInner:after {
    border-top-color: gold;
    border-left-color: gold;
    bottom: -190px;
    right: -143px;
}
<div class="circle">
    <div class="boltOuter">
        <div class="boltInner"></div>
    </div>
</div>

JS Fiddle: https://jsfiddle.net/o7gm6dsb/