Search code examples
htmlcsscss-shapes

CSS design - rainbow


I want to create a rainbow using only CSS only. Below is an image of what is required.

enter image description here

Here is my code (so far):

* {
  margin: 0;
  padding: 0;
}
#r {
  height: 80vw;
  width: 80vw;
  background-color: #f00;
  position: absolute;
  z-index: 1;
}
#o {
  height: 76vw;
  width: 76vw;
  background-color: #fe6230;
  position: absolute;
  top: 2vw;
  left: 2vw;
  z-index: 2;
}
#y {
  height: 72vw;
  width: 72vw;
  background-color: #fef600;
  position: absolute;
  top: 4vw;
  left: 4vw;
  z-index: 3;
}
#g {
  height: 68vw;
  width: 68vw;
  background-color: #00bc00;
  position: absolute;
  top: 6vw;
  left: 6vw;
  z-index: 4;
}
#b {
  height: 64vw;
  width: 64vw;
  background-color: #0048fe;
  position: absolute;
  top: 8vw;
  left: 8vw;
  z-index: 5;
}
#i {
  height: 60vw;
  width: 60vw;
  background-color: #000083;
  position: absolute;
  top: 10vw;
  left: 10vw;
  z-index: 6;
}
#v {
  height: 56vw;
  width: 56vw;
  background-color: #30009b;
  position: absolute;
  top: 12vw;
  left: 12vw;
  z-index: 7;
}
<div id="r">
</div>
<div id="o">
</div>
<div id="y">
</div>
<div id="g">
</div>
<div id="b">
</div>
<div id="i">
</div>
<div id="v">
</div>

The problem with my code is that I am unable to curve it (like in a real rainbow). I also need to hide half of this rainbow.


Solution

  • This could be done using a single div element with a :pseudo-element and box-shadow.

    div {
      position: relative;
      width: 300px;
      height: 150px;
      background: white;
      overflow: hidden;
      transform: scale(2);
      margin-left: 130px;
      margin-top: -50px;
    }
    div:after {
      position: absolute;
      content: '';
      width: 100px;
      height: 100px;
      top: 100px;
      left: 50px;
      border-radius: 50%;
      box-shadow: 0 0 0 5px #4200AB, 0 0 0 10px #000095, 0 0 0 15px #00ABFF, 0 0 0 20px #00C800, 0 0 0 25px #FFF800, 0 0 0 30px #FF7642, 0 0 0 35px #E40000;
    }
    <div></div>

    Example using vh / vw units.

    Demo on CodePen

    Looks awful in the snippet here because of the viewport ratio, better viewed on CodePen.

    div {
      position: relative;
      width: 95vw;
      height: 45vw;
      overflow: hidden;
      background: transparent;
      transform: translate(-50vw, -16.666vw);
      top: 8vw;
      left: 50vw;
    }
    div:after {
      position: absolute;
      content: '';
      width: 50%;
      height: 100%;
      top: 25vw;
      left: 25vw;
      border-radius: 50%;
      box-shadow: 0 0 0 2vw #4200AB, 0 0 0 4vw #000095, 0 0 0 6vw #00ABFF, 0 0 0 8vw #00C800, 0 0 0 10vw #FFF800, 0 0 0 12vw #FF7642, 0 0 0 14vw #E40000;
    }
    body {
      margin: 0;
    }
    <div></div>