Skip to content

Instantly share code, notes, and snippets.

@bobquest33
Created December 25, 2015 03:42
Show Gist options
  • Save bobquest33/d6fd9e7dde1f3668c78d to your computer and use it in GitHub Desktop.
Save bobquest33/d6fd9e7dde1f3668c78d to your computer and use it in GitHub Desktop.
Material Design Cards
// Controllers
div.controller-container
span#big.controller.is_current BIG CARD
span#medium.controller MEDIUM CARD
span#small.controller SMALL CARD
// Cards
.card.card--big
div.card__image(style='background-image: url(http://i.imgur.com/8ki2fuE.jpg)')
h2.card__title Kangaroo Valley Safari
span.card__subtitle By Mattia Astorino
p.card__text Located two hours south of Sydney in the Southern Highland of New South Wales...
div.card__action-bar
button.card__button SHARE
button.card__button LEARN MORE
(function(){
$(".controller").click(function(){
id = $(this).attr("id");
$(".controller-container").find(".is_current").removeClass("is_current");
$(this).addClass("is_current");
$(".card").attr('class', 'card card--' + id);
$("html").attr('class', 'bg--' + id);
});
})();
// Ripple function
(function(){
"use strict";
var colour = "#FF1744";
var opacity = 0.1;
var ripple_within_elements = ['input', 'button', 'a'];
var ripple_without_diameter = 0;
var overlays = {
items: [],
get: function(){
var $element;
for(var i = 0; i < overlays.items.length; i++){
$element = overlays.items[i];
if($element.transition_phase === false) {
$element.transition_phase = 0;
return $element;
}
}
$element = document.createElement("div");
$element.style.position = "absolute";
$element.style.opacity = opacity;
//$element.style.outline = "10px solid red";
$element.style.pointerEvents = "none";
$element.style.background = "-webkit-radial-gradient(" + colour + " 64%, rgba(0,0,0,0) 65%) no-repeat";
$element.style.background = "radial-gradient(" + colour + " 64%, rgba(0,0,0,0) 65%) no-repeat";
$element.style.transform = "translateZ(0)";
$element.transition_phase = 0;
$element.rid = overlays.items.length;
$element.next_transition = overlays.next_transition_generator($element);
document.body.appendChild($element);
overlays.items.push($element);
return $element;
},
next_transition_generator: function($element){
return function(){
$element.transition_phase++;
switch($element.transition_phase){
case 1:
$element.style[transition] = "all 500ms cubic-bezier(0.165, 0.840, 0.440, 1.000)";
$element.style.backgroundSize = $element.ripple_backgroundSize;
$element.style.backgroundPosition = $element.ripple_backgroundPosition;
setTimeout($element.next_transition, 0.2 * 1000); //now I know transitionend is better but it fires multiple times when multiple properties are animated, so this is simpler code and (imo) worth tiny delays
break;
case 2:
$element.style[transition] = "opacity 0.15s ease-in-out";
$element.style.opacity = 0;
setTimeout($element.next_transition, 0.15 * 1000);
break;
case 3:
overlays.recycle($element);
break;
}
};
},
recycle: function($element){
$element.style.display = "none";
$element.style[transition] = "none";
if($element.timer) clearTimeout($element.timer);
$element.transition_phase = false;
}
};
var transition = function(){
var i,
el = document.createElement('div'),
transitions = {
'WebkitTransition':'webkitTransition',
'transition':'transition',
'OTransition':'otransition',
'MozTransition':'transition'
};
for (i in transitions) {
if (transitions.hasOwnProperty(i) && el.style[i] !== undefined) {
return transitions[i];
}
}
}();
var click = function(event){
var $element = overlays.get(),
touch,
x,
y;
touch = event.touches ? event.touches[0] : event;
$element.style[transition] = "none";
$element.style.backgroundSize = "3px 3px";
$element.style.opacity = opacity;
if(ripple_within_elements.indexOf(touch.target.nodeName.toLowerCase()) > -1) {
x = touch.offsetX;
y = touch.offsetY;
var dimensions = touch.target.getBoundingClientRect();
if(!x || !y){
x = (touch.clientX || touch.x) - dimensions.left;
y = (touch.clientY || touch.y) - dimensions.top;
}
$element.style.backgroundPosition = x + "px " + y + "px";
$element.style.width = dimensions.width + "px";
$element.style.height = dimensions.height + "px";
$element.style.left = (dimensions.left) + "px";
$element.style.top = (dimensions.top + document.body.scrollTop + document.documentElement.scrollTop) + "px";
var computed_style = window.getComputedStyle(event.target);
for (var key in computed_style) {
if (key.toString().indexOf("adius") > -1) {
if(computed_style[key]) {
$element.style[key] = computed_style[key];
}
} else if(parseInt(key, 10).toString() === key && computed_style[key].indexOf("adius") > -1){
$element.style[computed_style[key]] = computed_style[computed_style[key]];
}
}
$element.style.backgroundPosition = x + "px " + y + "px";
$element.ripple_backgroundPosition = (x - dimensions.width) + "px " + (y - dimensions.width) + "px";
$element.ripple_backgroundSize = (dimensions.width * 2) + "px " + (dimensions.width * 2) + "px";
} else { //click was outside of ripple element
x = touch.clientX || touch.x || touch.pageX;
y = touch.clientY || touch.y || touch.pageY;
$element.style.borderRadius = "0px";
$element.style.left = (x - ripple_without_diameter / 2) + "px";
$element.style.top = (document.body.scrollTop + document.documentElement.scrollTop + y - ripple_without_diameter / 2) + "px";
$element.ripple_backgroundSize = ripple_without_diameter + "px " + ripple_without_diameter + "px";
$element.style.width = ripple_without_diameter + "px";
$element.style.height = ripple_without_diameter + "px";
$element.style.backgroundPosition = "center center";
$element.ripple_backgroundPosition = "center center";
$element.ripple_backgroundSize = ripple_without_diameter + "px " + ripple_without_diameter + "px";
}
$element.ripple_x = x;
$element.ripple_y = y;
$element.style.display = "block";
setTimeout($element.next_transition, 20);
};
if('ontouchstart' in window || 'onmsgesturechange' in window){
document.addEventListener("touchstart", click, false);
} else {
document.addEventListener("click", click, false);
}
}());
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
// SETTINGS
// ########################################
@import url(http://fonts.googleapis.com/css?family=Roboto:400,700,300);
@cta-color: #FF1744;
// BASIC STYLE
//########################################
:root {
transition: all 300ms;
&.bg--big {
background-color: #00BCD4; }
&.bg--medium {
background-color: #E53935; }
&.bg--small {
background-color: #4527A0; }
}
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
font-family: 'Roboto', sans-serif;
transform: translateZ(0);
font-weight: 400; }
// button reset
button {
border: none;
background: transparent; }
// controllers bar
.controller-container {
margin-bottom: 5%;
text-align: center; }
// controller element
.controller {
user-select: none;
display: inline-block;
margin: 0 20px;
font-size: 22px;
padding: 10px 0;
color: #FFF;
position: relative;
transition: all 100ms cubic-bezier(0.165, 0.840, 0.440, 1.000);
&:after {
content: "";
height: 3px;
display: block;
position: absolute;
bottom: 0;
width: 0;
transition: all 300ms cubic-bezier(0.165, 0.840, 0.440, 1.000);
background-color: #FFF; }
&.is_current:after {
width: 100%; }
&:hover, &.is_current {
transform: translate3d( 0, -5px, 0 );
cursor: pointer; }
}
// DEFAULT CARD AND ELEMENTS
//########################################
// basic card block
.card {
will-change: transform;
margin: 8px;
position: relative;
border-radius: 2px;
overflow: hidden;
background-color: #fafafa;
height: 35%;
width: 344px;
transition: all 400ms cubic-bezier(0.165, 0.840, 0.440, 1.000);
.z-1;
// hover status
&:hover {
cursor: pointer; }
}
// default card image element
.card__image {
position: absolute;
background-size: cover;
background-position: center bottom;
background-repeat: no-repat;
width: 100%;
height: 100%;
overflow: hidden;
display: block;
opacity: 0;
transition: all 200ms cubic-bezier(0.075, 0.820, 0.165, 1.000);
// image overlay
&:after {
content: "";
display: block;
position: absolute;
background-color: rgba(0,0,0,0.1);
top: 0;
left: 0;
right: 0;
transition: all 500ms;
bottom: 0; }
}
// default card title element
.card__title {
user-select: none;
font-size: 24px;
color: #FFF;
margin: 0;
position: absolute;
left: 0;
right: 0;
padding: 0 16px;
font-weight: 400;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
transition: all 200ms cubic-bezier(0.075, 0.820, 0.165, 1.000); }
// default card subtitle element
.card__subtitle {
user-select: none;
font-size: 14px;
display: block;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
color: #000;
left: 88px;
right: 0;
top: 45px;
position: absolute;
padding: 0 16px;
opacity: 0;
transition: all 200ms cubic-bezier(0.075, 0.820, 0.165, 1.000); }
// default card text element
.card__text {
user-select: none;
font-size: 14px;
display: block;
left: 0;
right: 0;
top: 100px;
padding: 16px;
margin: 0;
line-height: 1.6;
position: absolute;
color: #000;
overflow: hidden;
transition: width 200ms cubic-bezier(0.075, 0.820, 0.165, 1.000);
transition: delay 0.1s; }
// default card action bar element
.card__action-bar {
user-select: none;
position: absolute;
bottom: 0;
top: auto;
left: 0;
right: 0;
padding: 0 8px;
border-top: 1px solid #E0E0E0;
boz-sizing: border-box;
height: 52px;
transition: left 200ms cubic-bezier(0.075, 0.820, 0.165, 1.000); }
// default card button element
.card__button {
outline: none;
position: relative;
display: inline-block;
line-height: 52px;
padding: 0 16px;
color: @cta-color; }
// CARDS MODIFIERS
//########################################
// Big modifier
.card--big {
.z-5;
height: 304px;
min-height: 304px;
// image element
.card__image {
border-radius: 1px 1px 0 0;
left: 0;
right: 0;
top: 0;
opacity: 1;
max-height: 176px; }
// title element
.card__title {
top: 135px; }
// text element
.card__text {
top: 176px; }
.card__action-bar {
left: 0; }
}
// Medium modifier
.card--medium {
.z-3;
height: 208px;
min-height: 208px;
// image element
.card__image {
border-radius: 1px 1px 0 0;
left: 0;
right: 0;
top: 0;
max-height: 0;
opacity: 0;
transition-duration: 300ms; }
// title element
.card__title {
color: @cta-color;
top: 16px; }
// text element
.card__text {
font-size: 16px;
top: 50px; }
.card__action-bar {
left: 0; }
}
// Small modifier
.card--small {
.z-2;
height: 136px;
min-height: 136px;
// image element
.card__image {
border-radius: 1px 0 0 1px;
left: 0;
top: 0;
width: 88px;
opacity: 1;
max-height: 136px;
// image overlay
&:after {
opacity: 0; }
}
// title element
.card__title {
color: #000;
left: 88px;
top: 8px; }
.card__subtitle {
opacity: 1;
left: 88px; }
// text element
.card__text {
top: 30px;
opacity: 0; }
// actionbar element
.card__action-bar {
left: 88px; }
}
// MIXINS
//########################################
// z-depth official shadows
// (https://www.polymer-project.org/components/paper-elements/demo.html#paper-shadow)
.z-1() { box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37); }
.z-2() { box-shadow: 0 6px 10px 0 rgba(0, 0, 0, 0.3), 0 2px 2px 0 rgba(0, 0, 0, 0.2); }
.z-3() { box-shadow: 0 13px 25px 0 rgba(0, 0, 0, 0.3), 0 11px 7px 0 rgba(0, 0, 0, 0.19); }
.z-4() { box-shadow: 0 20px 40px 0 rgba(0, 0, 0, 0.3), 0 14px 12px 0 rgba(0, 0, 0, 0.17); }
.z-5() { box-shadow: 0 27px 55px 0 rgba(0, 0, 0, 0.3), 0 17px 17px 0 rgba(0, 0, 0, 0.15); }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment