Skip to content

Instantly share code, notes, and snippets.

@ja-k-e
Created August 7, 2015 04:55
Show Gist options
  • Select an option

  • Save ja-k-e/79cf453407fa7f723faf to your computer and use it in GitHub Desktop.

Select an option

Save ja-k-e/79cf453407fa7f723faf to your computer and use it in GitHub Desktop.
CSS Hex Cube

CSS Hex Cube

My attempt at making something notable for #neonHexagonsWeekend

Ripped off half this code from something I was working on a while ago. We'll see if the original ends up becoming public.

A Pen by Jake Albaugh on CodePen.

License.

%figure.hex
%span.cube
- (1..6).each do |i|
%span{:class => "side-#{i}"}
%span.alpha
- (1..3).each do |i|
%span{:class => "alpha-#{i}"}
//
// variables
//
// color map
$colors: (
// other global colors
'global': (
1: #888,
2: #666,
3: #444,
neon: #ADFF00
),
'alpha': (
1: transparentize(#fff, 0.8),
2: transparentize(#000, 0.8),
3: transparentize(#000, 0.9)
)
);
// size map
$hex-radius: 170px;
$sizes: (
// triangle side
hex-radius: $hex-radius,
// triangle height
hex-segment-height: 1.73205080757 / 2 * $hex-radius,
// explosion size
explode: $hex-radius / 2
);
// rotations map
$rotation-amount: (360deg/6);
$rotations: (
rotation-1: $rotation-amount * 1 - $rotation-amount,
rotation-2: $rotation-amount * 2 - $rotation-amount,
rotation-3: $rotation-amount * 3 - $rotation-amount,
rotation-4: $rotation-amount * 4 - $rotation-amount,
rotation-5: $rotation-amount * 5 - $rotation-amount,
rotation-6: $rotation-amount * 6 - $rotation-amount
);
// timing map
$total-time: 6000ms;
$assembly-time: $total-time * 0.55;
$border-time: $total-time * 0.2;
$timings: (
// side animation time (out of max assembly time)
side-in-increment: ($assembly-time * 0.52) / 6,
// starting times for each hexagon assembly
o-in: $assembly-time * 0.28,
// starting times for each hexagon border color change
o-border-in: $assembly-time,
// border color change time
border: $border-time * 0.5,
// start rotation
alpha-fade-in: $border-time + $assembly-time
);
//
// functions
//
// retrieve color from map ie. `color(light, 1)`
@function color($color-group, $color-name) {
@return map-get(map-get($colors, $color-group), $color-name);
}
// retrieve size from map ie. `size(hex-radius)`
@function size($size-name) {
@return map-get($sizes, $size-name);
}
// retrieve rotation from map ie. `rotation(1)`
@function rotation($number) {
@return map-get($rotations, rotation-#{$number});
}
// retrieve timing from map ie. `timing(base-time)`
@function timing($timing) {
@return map-get($timings, $timing);
}
//
// style mixins
//
// cube structure
@mixin cube-base($segment-height, $cube-radius) {
// positioning and sizing
position: absolute; display: block;
width: $cube-radius * 2; height: $segment-height * 2;
// center cube in parent context
top: calc(50% - #{$segment-height}); left: calc(50% - #{$cube-radius});
// each side
span {
position: absolute;
display: block;
transform-origin: 50% 50%;
// two trianges per side
&::before, &::after {
content: '';
position: absolute;
height: 0; width: 0;
border-left: $cube-radius / 2 solid transparent;
border-right: $cube-radius / 2 solid transparent;
}
}
// initial triangle border styles
$border-style-light: $segment-height solid color('global', 1);
$border-style-med: $segment-height solid color('global', 2);
$border-style-dark: $segment-height solid color('global', 3);
.side-6 {
&::before { border-bottom: $border-style-light }
&::after { border-top: $border-style-light }
}
.side-4, .side-5 {
&::before { border-bottom: $border-style-med }
&::after { border-top: $border-style-med }
}
.side-1, .side-2, .side-3 {
&::before { border-bottom: $border-style-dark }
&::after { border-top: $border-style-dark }
}
// side positioning
.side-1 { z-index: 1; bottom: 0; right: 0; } // bottom
.side-2 { z-index: 1; top: 0; right: 0; } // back
.side-3 { z-index: 5; right: 0; } // right
.side-4 { z-index: 5; bottom: 0; left: 0; } // front
.side-5 { z-index: 4; left: 0; } // left
.side-6 { z-index: 6; top: 0; left: 0; } // top
// side container size (portrait or landscape)
.side-1, .side-2, .side-4, .side-6 {
height: $segment-height; width: $cube-radius * 1.5;
}
.side-3, .side-5 {
height: $segment-height * 2; width: $cube-radius;
}
// side positioning and unique color
.side-3, .side-5 { &::before { top: 0; } &::after { bottom: 0; } }
.side-2, .side-4 { &::before { right: 0; } &::after { left: 0; } }
.side-6, .side-1 { &::before { left: 0; } &::after { right: 0; } }
}
// cube animations handled outside of
@mixin cube-animations($prefix) {
// each side
span {
opacity: 0;
// side animation
animation-delay: timing(#{$prefix}-in);
animation-timing-function: ease-out;
animation-fill-mode: forwards;
// two trianges per side
&::before, &::after {
// border color animation
animation: #{$prefix}-triangle timing(border) ease-out timing(#{$prefix}-border-in) forwards;
}
}
// side animations (delaying increments per side)
@for $i from 1 through 6 {
.side-#{$i} {
animation-name: side-#{$i};
animation-duration: timing(side-in-increment) * $i;
}
}
}
// alpha structure
@mixin alpha-base($segment-height, $cube-radius) {
// positioning and sizing
position: absolute; display: block;
z-index: 9;
width: $cube-radius * 2; height: $segment-height * 2;
// center cube in parent context
top: calc(50% - #{$segment-height}); left: calc(50% - #{$cube-radius});
opacity: 0;
// fade animation
animation: fade timing(border) linear timing(o-border-in) forwards;
// each side
span {
position: absolute;
display: block;
height: $segment-height; width: $cube-radius;
transform-origin: 50% 50%;
// two trianges per side
&::before, &::after {
content: '';
animation-duration: 6s;
animation-timing-function: ease-in-out;
animation-delay: timing(alpha-fade-in);
animation-iteration-count: infinite;
position: absolute;
height: 0; width: 0;
border-left: $cube-radius / 2 solid transparent;
border-right: $cube-radius / 2 solid transparent;
}
}
$border-style-light: $segment-height solid color('global', light);
.alpha-1 {
top: 0; left: 0; // top
&::before { left: 0; animation-name: alpha-1-b; border-bottom: $segment-height solid color('alpha', 1) }
&::after { right: 0; animation-name: alpha-1-a; border-top: $segment-height solid color('alpha', 1) }
}
.alpha-2 {
top: 0; right: 0; // right
&::before { top: 0; animation-name: alpha-2-b; border-bottom: $segment-height solid color('alpha', 2) }
&::after { bottom: 0; animation-name: alpha-2-a; border-top: $segment-height solid color('alpha', 2) }
}
.alpha-3 {
bottom: 0; left: 0; // bottom
&::before { right: 0; animation-name: alpha-3-b; border-bottom: $segment-height solid color('alpha', 3) }
&::after { left: 0; animation-name: alpha-3-a; border-top: $segment-height solid color('alpha', 3) }
}
// alpha container size (portrait or landscape)
.alpha-1, .alpha-3 {
height: $segment-height; width: $cube-radius * 1.5;
}
.alpha-2 {
height: $segment-height * 2; width: $cube-radius;
}
}
//
// styles
//
// hex
.hex {
width: size(hex-radius) * 2;
height: size(hex-segment-height) * 2;
position: relative;
margin: 100px auto;
}
// only use the mixins
.cube {
@include cube-base(size(hex-segment-height), size(hex-radius));
@include cube-animations('o');
}
.alpha {
@include alpha-base(size(hex-segment-height), size(hex-radius));
}
// body
body { background-color: #2f2f2f; }
//
// animation mixins
//
@mixin keyframes($name) {
@keyframes #{$name} {
@content;
}
}
//
// animations
//
// alpha fade animation
@keyframes fade {
from { opacity: 0 }
to { opacity: 1 }
}
// alpha fade animation
@keyframes alpha-1-b {
0%, 100% { border-bottom-color: color('alpha', 1); }
33.33% { border-bottom-color: color('alpha', 3); }
66.66% { border-bottom-color: color('alpha', 2); }
}
@keyframes alpha-1-a {
0%, 100% { border-top-color: color('alpha', 1); }
33.33% { border-top-color: color('alpha', 3); }
66.66% { border-top-color: color('alpha', 2); }
}
@keyframes alpha-2-b {
0%, 100% { border-bottom-color: color('alpha', 2); }
33.33% { border-bottom-color: color('alpha', 1); }
66.66% { border-bottom-color: color('alpha', 3); }
}
@keyframes alpha-2-a {
0%, 100% { border-top-color: color('alpha', 2); }
33.33% { border-top-color: color('alpha', 1); }
66.66% { border-top-color: color('alpha', 3); }
}
@keyframes alpha-3-b {
0%, 100% { border-bottom-color: color('alpha', 3); }
33.33% { border-bottom-color: color('alpha', 2); }
66.66% { border-bottom-color: color('alpha', 1); }
}
@keyframes alpha-3-a {
0%, 100% { border-top-color: color('alpha', 3); }
33.33% { border-top-color: color('alpha', 2); }
66.66% { border-top-color: color('alpha', 1); }
}
// mixin for triangle animation
@mixin triangle-animation($color) {
border-top-color: $color;
border-bottom-color: $color;
}
// triangle color animation
@keyframes o-triangle {
0% { @include triangle-animation(color('global', 1));}
100% { @include triangle-animation(color('global', neon)); }
}
// side-level animations
$inc: size(explode);
$bg-scale: 0.75; // background
$mg-scale: 1.00; // midground
$fg-scale: 1.10; // foreground
// redundant styles for side animations depth of field only specific for initial states
@mixin scaleFade-0 ($dof) { opacity: 0; transform: scale($dof); }
@mixin scaleFade-1 () { opacity: 1; transform: scale($mg-scale); }
// the actual position-specific keyframes.
@keyframes side-1 {
0% { @include scaleFade-0($bg-scale); bottom: -$inc; right: -$inc; }
100% { @include scaleFade-1(); bottom: 0; right: 0; }
}
@keyframes side-2 {
0% { @include scaleFade-0($bg-scale); top: -$inc * 0.5; right: -$inc; }
100% { @include scaleFade-1(); top: 0; right: 0; }
}
@keyframes side-3 {
0% { @include scaleFade-0($fg-scale); right: -$inc * 0.5; }
100% { @include scaleFade-1(); right: 0; }
}
@keyframes side-4 {
0% { @include scaleFade-0($bg-scale); bottom: -$inc * 0.5; left: -$inc; }
100% { @include scaleFade-1(); bottom: 0; left: 0; }
}
@keyframes side-5 {
0% { @include scaleFade-0($bg-scale); left: -$inc * 1.5; }
100% { @include scaleFade-1(); left: 0; }
}
@keyframes side-6 {
0% { @include scaleFade-0($fg-scale); top: -$inc; left: -$inc; }
100% { @include scaleFade-1(); top: 0; left: 0; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment