// 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(https://placeimg.com/640/480/nature)')
  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
View Compiled

  // SETTINGS
  // ########################################
 
  @import url(https://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: -100%;
          right: 0;
          top: 0;
          max-height: 0;
          opacity: 0; }

          // 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); }
View Compiled
(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);
	}
}());
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js