Creating a natural flame flicker with random()!
A Pen by Joseph Fusco on CodePen.
| <h1>SASS Candle Flicker</h1> | |
| <input id="toggle" type="checkbox"> | |
| <label for="toggle"></label> | |
| <div class="candle"> | |
| <div class="flicker"></div> | |
| </div> |
Creating a natural flame flicker with random()!
A Pen by Joseph Fusco on CodePen.
| // demonstration purposes only, please don't actually use these settings as this compiles to over 2000 lines :P | |
| $color-flame--base: #FEE3AC; | |
| $flame-height--base: 80px; | |
| $tolerance: .3; | |
| $flickers: ( | |
| // opacity : frequency | |
| 0 : 100, | |
| .23 : 30, | |
| .45 : 90, | |
| .32 : 40 | |
| // Frequency is how many times the flame could possibly hit that opacity level for every 100 frames (increments of 10). Since the hitting is random, there is a great chance that keyframe percentages will be repeated. | |
| // Keep in mind this compiles to over 2000 lines at its current settings. Try to keep your frequency below 50 for production. | |
| ); | |
| body{ | |
| background-color: #000; | |
| text-align: center; | |
| } | |
| h1{ | |
| font-family: sans-serif; | |
| color: #222; | |
| font-size: 3em; | |
| margin: 20px 0px; | |
| text-shadow: 0 -1px 2px #333; | |
| } | |
| .candle{ | |
| width: 300px; | |
| height: 300px; | |
| margin: 0px auto; | |
| background: url('http://i.imgur.com/4I5IR6Q.jpg') no-repeat; | |
| background-size: contain; | |
| position: relative; | |
| } | |
| .flicker{ | |
| position: absolute; | |
| width: 10px; | |
| height: $flame-height--base; | |
| border-radius: 50%; | |
| bottom: 60%; | |
| left: 48%; | |
| background-color: $color-flame--base; | |
| box-shadow: 0 0 0px 0px $color-flame--base; | |
| -webkit-animation: 10s flicker infinite; | |
| animation: 10s flicker infinite; | |
| } | |
| @keyframes flicker{ | |
| $angle: 0; | |
| @each $level, $frequency in $flickers{ | |
| @for $i from 1 through 100{ | |
| @if $i % (floor(100 / $frequency)) == 0{ | |
| $r: random(100); | |
| #{($r)}%{ | |
| $amount: floor($i / 10); | |
| $color-flame: darken($color-flame--base, $amount); | |
| opacity: $level; | |
| $f-blur: $i * .33; | |
| $f-spread: $f-blur * .5; | |
| box-shadow: 0 0 #{$f-blur}px #{$f-spread}px $color-flame; | |
| @if $i % 2 == 0{ | |
| $angle: $amount / 2; | |
| } | |
| @else{ | |
| $angle: 0 - $amount / 2; | |
| } | |
| @if $level <= $tolerance { | |
| height: 0; | |
| } | |
| @else if $level <= ($tolerance - $flame-height--base * .1){ | |
| height: ( ($flame-height--base - $flame-height--base * .1) - 2 * $amount); | |
| } | |
| @else{ | |
| height: ( $flame-height--base - 2 * $amount); | |
| } | |
| -webkit-transform: rotate(#{$angle}deg); | |
| transform: rotate(#{$angle}deg); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| // controls | |
| label{ | |
| position: fixed; | |
| top: 300px; | |
| z-index: 100; | |
| left: 0; | |
| right: 0; | |
| margin: 0 auto; | |
| width: 150px; | |
| text-align: center; | |
| font-family: sans-serif; | |
| color: #FFF; | |
| padding: 10px; | |
| background-color: #111; | |
| cursor: pointer; | |
| border-radius: 4px; | |
| &:after{ | |
| content: 'remove candle'; | |
| } | |
| &:hover{ | |
| background-color: #222; | |
| } | |
| } | |
| input{ | |
| display: none; | |
| &:checked{ | |
| + label{ | |
| &:after{ | |
| content: 'show candle'; | |
| } | |
| } | |
| ~ .candle{ | |
| background: none; | |
| } | |
| } | |
| } |