Skip to content

Instantly share code, notes, and snippets.

@IgnetStudio
Created April 12, 2015 15:35
Show Gist options
  • Select an option

  • Save IgnetStudio/4e82acc0b678c9320f6b to your computer and use it in GitHub Desktop.

Select an option

Save IgnetStudio/4e82acc0b678c9320f6b to your computer and use it in GitHub Desktop.
Reactive CSS Transitions

Reactive CSS Transitions

These simple CSS blocks are alive. Each block reacts to its neighbors by transforming border-radius and color. Endless block formations, endless reactions between them.

A Pen by Yogev Ahuvia on CodePen.

License.

// Magic Number (don't go too low):
var blockSize = 100;
/* Reactive CSS Transitions © Yogev Ahuvia
* =======================================
* These simple CSS blocks are alive. Each
* block reacts to its neighbors by
* transforming border-radius and color.
* Endless block formations, endless
* reactions between them.
* ---------------------------------------
* Works best on Google Chrome.
*/
var elements = [];
var x, y, index, isEvenRow;
var $container, $window;
function init() {
$container = $('body');
$window = $(window);
x = (blockSize * 0.25);
y = -(blockSize * 0.5);
index = 0;
isEvenRow = false;
}
$(document).ready(function() {
init();
build();
});
$(window).resize(function() {
init();
build();
onCheck();
});
function build() {
do {
updateRowFlag();
if (!elements[index]) {
createNewBlock(x,y,index);
} else {
var elemObj = elements[index];
$(elemObj.input).css({'left': x+'px', 'top': y+'px'});
$(elemObj.block).css({'left': x+'px', 'top': y+'px'});
}
updateCoords();
index++;
} while (y <= $window.height() + blockSize);
}
function createNewBlock(x,y,index) {
var style = ' style="width: '+blockSize+'px; height: '+blockSize+'px; left: '+x+'px; top: '+y+'px;"';
var $input = $('<input type="checkbox"'+style+'></input>');
var $block = $('<div class="block"'+style+'></div>');
$input.on('click', onCheck);
elements.push({ input : $input[0], block : $block[0] });
$container.append($input, $block);
}
function updateRowFlag() {
if (x > $window.width()) {
isEvenRow = !isEvenRow;
x = (isEvenRow ? -(blockSize*0.5) : (blockSize*0.25));
y += (blockSize*0.75);
}
}
function updateCoords() {
x += blockSize + (blockSize * 0.5);
}
function getNeighbours(index, elem) {
var neighbors = { Ne: undefined, NEe: undefined, Ee: undefined, SEe: undefined, Se: undefined, SWe: undefined, We: undefined, NWe: undefined };
var Nc = { x : elem.offsetLeft + (elem.offsetWidth / 2),
y : elem.offsetTop - elem.offsetHeight };
var NEc = { x : elem.offsetLeft + elem.offsetWidth,
y : elem.offsetTop - (elem.offsetHeight / 2) };
var SEc = { x : elem.offsetLeft + elem.offsetWidth,
y : elem.offsetTop + elem.offsetHeight };
var Sc = { x : elem.offsetLeft + (elem.offsetWidth / 2),
y : elem.offsetTop + (elem.offsetHeight * 2) };
var SWc = { x : elem.offsetLeft,
y : elem.offsetTop + elem.offsetHeight };
var NWc = { x : elem.offsetLeft,
y : elem.offsetTop - (elem.offsetHeight / 2) };
for (var i = 0; i < elements.length; i++) {
var cur = elements[i].input;
if (isCoordOnElement(Nc.x, Nc.y, cur)) {
neighbors.Ne = cur;
}
else if (isCoordOnElement(NEc.x, NEc.y, cur)) {
neighbors.NEe = cur;
}
else if (isCoordOnElement(SEc.x, SEc.y, cur)) {
neighbors.SEe = cur;
}
else if (isCoordOnElement(Sc.x, Sc.y, cur)) {
neighbors.Se = cur;
}
else if (isCoordOnElement(SWc.x, SWc.y, cur)) {
neighbors.SWe = cur;
}
else if (isCoordOnElement(NWc.x, NWc.y, cur)) {
neighbors.NWe = cur;
}
}
if (elements[index-1])
neighbors.We = elements[index-1].input;
if (elements[index+1])
neighbors.Ee = elements[index+1].input;
return neighbors;
}
function isCoordOnElement(x, y, elem) {
if (x > elem.offsetLeft &&
x < (elem.offsetLeft + elem.offsetWidth) &&
y > elem.offsetTop &&
y < (elem.offsetTop + elem.offsetHeight)) {
return true;
}
return false;
}
function clearEffects($elem) {
$elem.removeClass('Ns NWs NEs NWNEs Es SEs NESEs Ss SWs SESWs Ws NWs NWSWs NSs WEs');
}
function onCheck(e) {
for (var i = 0; i < elements.length; i++) {
var elemObj = elements[i];
var neighbors = getNeighbours(i, elemObj.input);
var $block = $(elemObj.block);
clearEffects($block);
if (neighbors.Ne && neighbors.Ne.checked)
$block.addClass('Ns');
if (neighbors.NEe && neighbors.NEe.checked)
$block.addClass('NEs');
if (neighbors.Ee && neighbors.Ee.checked)
$block.addClass('Es');
if (neighbors.SEe && neighbors.SEe.checked)
$block.addClass('SEs');
if (neighbors.Se && neighbors.Se.checked)
$block.addClass('Ss');
if (neighbors.SWe && neighbors.SWe.checked)
$block.addClass('SWs');
if (neighbors.We && neighbors.We.checked)
$block.addClass('Ws');
if (neighbors.NWe && neighbors.NWe.checked)
$block.addClass('NWs');
}
}
@import "compass/css3";
input {
display: block;
position: absolute;
appearance: none;
cursor: pointer;
z-index: 1;
transform-origin: 50% 50%;
transform: rotate(45deg);
opacity: 0;
&:hover + .block {
box-shadow: 1px 1px 1px 0px rgba(0,0,0,1), inset 1px 1px 1px 0px rgba(255,255,255,1);
background: #ff9ea3;
}
&:checked + .block {
background: #F9D423;
border-radius: 100%;
&.Ns {
border-top-left-radius: 5px;
}
&.NEs {
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
&.Es {
border-top-right-radius: 5px;
}
&.SEs {
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
&.Ss {
border-bottom-right-radius: 5px;
}
&.SWs {
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
&.Ws {
border-bottom-left-radius: 5px;
}
&.NWs {
border-bottom-left-radius: 5px;
border-top-left-radius: 5px;
}
}
}
.block {
position: absolute;
background: #FF4E50;
border-radius: 5px;
transition: border-radius 750ms, background 500ms;
transform-origin: 50% 50%;
transform: rotate(45deg);
box-shadow: 1px 1px 1px 0px rgba(0,0,0,1), inset 1px 1px 1px 0px rgba(255,255,255,0.8);
}
body {
background: #222;
overflow: hidden;
position: absolute;
width: 100%;
height: 100%;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment