CodePen

HTML

            
              <link href='//fonts.googleapis.com/css?family=Raleway:400,200,600' rel='stylesheet' type='text/css'>

<header>
  <a class="off-canvas-trigger" href="#">
    <span>T</span><span>o</span><span>u</span><span>c</span><span>h</span>
    <span> M</span><span>e</span>
  </a>
  <nav class="off-canvas">
    <ul class="off-canvas__list">
      <li><a class="off-canvas__link" href="#">Sweettune</a></li>
      <li><a class="off-canvas__link" href="#">Boyfriend</a></li>
      <li><a class="off-canvas__link" href="#">C*-ute</a></li>
      <li><a class="off-canvas__link" href="#">Nine Muses</a></li>
      <li><a class="off-canvas__link" href="#">EXO-K</a></li>
      <li><a class="off-canvas__link" href="#">Melons</a></li>
      <li><a class="off-canvas__link" href="#">Aroma</a></li>
    </ul>
  </nav>
</header>
<main>
  <section>
    <h1>OH GIRL</h1>
  </section>
</main>
<footer>
</footer>
            
          
!

CSS

            
              // ========================
// Modernizr
// ========================

// Modernizr mixin to create .modernizr selector
// http://codepen.io/sturobson/pen/xcdha

@mixin css($property, $support: true) {
    @if $support == true {
        .#{$property} & {
            @content;
        }
    }
    @else {
        .no-#{$property} & {
            @content;
        }
    }
}


// ========================
// Variables
// ========================

// Making accent white will simplify the entire scheme
$accent: #ff6589;
$background: #013742;

$general-transition-speed: .4s;
$canvas-transition-speed: .6s;

// wave
// x
// jumbled-x
$trigger-active-style: jumbled-x;

// square - no extra styles applied
// rounded
// leaf
// circle
$trigger-active-shape: leaf;

// from the inactive location of the canvas to the active location
// from: left-to-right 
// from: top-to-bottom
$canvas-direction: left-to-right;

// ! future addtion
// should the canvas be completely hidden or slightly overlay the content as a hidden element
// sometimes a subtle effect can be more elegant
// harsh
// subtle
$canvas-shift: harsh;

// static - no extra styles applied
// traditional
// scale
// push-rotate
$content-push: push-rotate;


// ========================
// Resets
// ========================

html {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
  position: relative;
}

*:before,
*:after { 
  pointer-events: none; 
}

// ========================
// Structure
// ========================

html { 
  height: 100%;
  font-family: 'Raleway', sans-serif;
  background: $background;
  }

  body { 
    height: 100%;
    min-height: 100%;
    margin: 0;
    color: #fff;
  }


// ========================
// HTML
// ========================

a {
  text-decoration: none;
  transition: $general-transition-speed;
}


// ========================
// Headings
// ========================

h1 { 
  font-size: 7vw;
  font-weight: 200;
  text-align: center;
  color: #ff6589;
  
  &:first-letter {
    font-size: 9vw;
  }
  
}


// ========================
// Off Canvas Trigger
// ========================

.off-canvas-trigger {
  display: block;
  padding: 1.75em 1em 1.75em 5em;
  font-size: 1.75em;
  background: rgba(#fff, .05);
  color: #fff;
  transition: $general-transition-speed;
  
  &:before {
    position: absolute;
    top: 22%;
    left: 1em;
    // Could these be a variable
    // Maybe multiplying by itself could get the positioning needed
    height: .5em;
    width: .5em;
    content: '';
    background: $accent;
    border-radius: 0;
    box-shadow: 
      .5em 0 0 0 adjust-hue($accent, 20%),
      1em 0 0 0 adjust-hue($accent, 40%),
      1.5em 0 0 0 adjust-hue($accent, 60%),
      2em 0 0 0 adjust-hue($accent, 80%),
      2.5em 0 0 0 adjust-hue($accent, 100%),
   
      0 1em 0 0 adjust-hue($accent, 0),
      .5em 1em 0 0 adjust-hue($accent, 20%),
      1em 1em 0 0 adjust-hue($accent, 40%),
      1.5em 1em 0 0 adjust-hue($accent, 60%),
      2em 1em 0 0 adjust-hue($accent, 80%),
      2.5em 1em 0 0 adjust-hue($accent, 100%),
      
      0 2em 0 0 adjust-hue($accent, 0),
      .5em 2em 0 0 adjust-hue($accent, 20%),
      1em 2em 0 0 adjust-hue($accent, 40%),
      1.5em 2em 0 0 adjust-hue($accent, 60%),
      2em 2em 0 0 adjust-hue($accent, 80%),
      2.5em 2em 0 0 adjust-hue($accent, 100%);
    transition: $general-transition-speed;
  }
  
  &:hover {
    background: rgba(#fff, .1);
    
    &:before {
      background: adjust-hue($accent, 100%);
      box-shadow: 
      .5em 0 0 0 adjust-hue($accent, 80%),
      1em 0 0 0 adjust-hue($accent, 60%),
      1.5em 0 0 0 adjust-hue($accent, 40%),
      2em 0 0 0 adjust-hue($accent, 20%),
      2.5em 0 0 0 adjust-hue($accent, 0),
   
      0 1em 0 0 adjust-hue($accent, 100%),
      .5em 1em 0 0 adjust-hue($accent, 80%),
      1em 1em 0 0 adjust-hue($accent, 60%),
      1.5em 1em 0 0 adjust-hue($accent, 40%),
      2em 1em 0 0 adjust-hue($accent, 20%),
      2.5em 1em 0 0 adjust-hue($accent, 0),
      
      0 2em 0 0 adjust-hue($accent, 100%),
      .5em 2em 0 0 adjust-hue($accent, 80%),
      1em 2em 0 0 adjust-hue($accent, 60%),
      1.5em 2em 0 0 adjust-hue($accent, 40%),
      2em 2em 0 0 adjust-hue($accent, 20%),
      2.5em 2em 0 0 adjust-hue($accent, 0);
    }
    
  }
  
  .off-canvas-active & {
    background: rgba(#fff, .1);
    
    &:before {
      background: $accent;
      
      // Trigger Styles
      @if $trigger-active-style == wave {
        // Stacking and order is maintained to preserve expected transition
        box-shadow: 
          .5em .5em 0 0 adjust-hue($accent, 20%),
          1em 1em 0 0 adjust-hue($accent, 40%),
          1.5em .5em 0 0 adjust-hue($accent, 60%),
          2em 0 0 0 adjust-hue($accent, 80%),
          2.5em .5em 0 0 adjust-hue($accent, 100%),

          0 1em 0 0 adjust-hue($accent, 0),
          .5em 1.5em 0 0 adjust-hue($accent, 20%),
          1em 2em 0 0 adjust-hue($accent, 40%),
          1.5em 1.5em 0 0 adjust-hue($accent, 60%),
          2em 1em 0 0 adjust-hue($accent, 80%),
          2.5em 1.5em 0 0 adjust-hue($accent, 100%),

          0 2em 0 0 transparent,
          .5em 2em 0 0 transparent,
          1em 2em 0 0 transparent,
          1.5em 2em 0 0 transparent,
          2em 2em 0 0 transparent,
          2.5em 2em 0 0 transparent;
      }
      
      @if $trigger-active-style == x {
        // In order for the button to be equidistant from the left and right
        left: 1.25em;
        box-shadow: 
          .5em .5em 0 0 adjust-hue($accent, 20%),
          1em 1em 0 0 adjust-hue($accent, 40%),
          1.5em .5em 0 0 adjust-hue($accent, 60%),
          2em 0 0 0 adjust-hue($accent, 80%),
          2.5em .5em 0 0 transparent,

          0 2em 0 0 adjust-hue($accent, 0),
          .5em 1.5em 0 0 adjust-hue($accent, 20%),
          1em 2em 0 0 transparent,
          1.5em 1.5em 0 0 adjust-hue($accent, 60%),
          2em 2em 0 0 adjust-hue($accent, 80%),
          2.5em 1.5em 0 0 transparent,

          0 2em 0 0 transparent,
          .5em 2em 0 0 transparent,
          1em 2em 0 0 transparent,
          1.5em 2em 0 0 transparent,
          2em 2em 0 0 transparent,
          2.5em 2em 0 0 transparent;
      }
      
      @if $trigger-active-style == jumbled-x {
        // In order for the button to be equidistant from the left and right
        left: 1.25em;
        // This is actually just a trick
        // By removing the items that are transparent during "x" the box-shadow is forced to redraw and transition the order
        box-shadow: 
          .5em .5em 0 0 adjust-hue($accent, 20%),
          1em 1em 0 0 adjust-hue($accent, 40%),
          1.5em .5em 0 0 adjust-hue($accent, 60%),
          2em 0 0 0 adjust-hue($accent, 80%),

          0 2em 0 0 adjust-hue($accent, 0),
          .5em 1.5em 0 0 adjust-hue($accent, 20%),
          1.5em 1.5em 0 0 adjust-hue($accent, 60%),
          2em 2em 0 0 adjust-hue($accent, 80%),
      }
      
      // Trigger Shapes
      @if $trigger-active-shape == rounded {
        border-radius: .1em;
      }
      
      @if $trigger-active-shape == circle {
        // Keep this number relatively low
        // If it's any higher that means the browser will have to transition that range
        border-radius: .25em;
      }
      
      @if $trigger-active-shape == leaf {
        border-radius: .15em 0 .15em;
      }
      
    }
    
  }
  
    // T o u c h  M e colors
    span {
      color: $accent;
      transition: color $general-transition-speed;
      &:nth-child(2) { color: adjust-hue($accent, 20%); }
      &:nth-child(3) { color: adjust-hue($accent, 40%); }
      &:nth-child(4) { color: adjust-hue($accent, 60%); }
      &:nth-child(5) { color: adjust-hue($accent, 80%); }
      &:nth-child(6) { color: adjust-hue($accent, 100%); }
      &:nth-child(7) { color: adjust-hue($accent, 120%); }
    }
  
  // Hover redeclared to maintain flow of the document
  // Is this the best approach?
  &:hover {
    span {
      color: adjust-hue($accent, 120%);
      &:nth-child(2) { color: adjust-hue($accent, 100%); }
      &:nth-child(3) { color: adjust-hue($accent, 80%); }
      &:nth-child(4) { color: adjust-hue($accent, 60%); }
      &:nth-child(5) { color: adjust-hue($accent, 40%); }
      &:nth-child(6) { color: adjust-hue($accent, 20%); }
      &:nth-child(7) { color: $accent; }
    }
  }
}


// ========================
// Off Canvas
// ========================

// The takeaway:
//   inactive state - transform: translate(-100%, 0);
//   active state - transform: translate(0, 0);
.off-canvas {
  position: fixed;
  left: 0;
  height: 100%;
  min-height: 100%;
  // Reinvestigate - Mobile Safari doesn't render the scroll bar here
  // If the content is very tall consider condensing via height based media queries
  // You could also enable these properties at a particular viewport height
  overflow: auto;
  overflow-y: scroll;
  overflow-scrolling: touch;
  // A little pushin for the cushion
  // Does the scroll work as expected without padding-bottom?
  padding: .75em 0 10em;
  // Prevent the canvas from being interactive when inactive
  pointer-events: none;
  background: rgba(#fff, .1);
  transition: $canvas-transition-speed;
  
  @if $canvas-direction == left-to-right {
    top: 8.2em;
    width: 75%;
    
    // Push the canvas out of the viewport by default
    // Regardless of the canvas's width, translate it completely out of sight
    @include css(csstransforms3d) {
      transform: translate3d(-100%, 0, 0);
    }
    
    @include css(csstransforms3d, false) {
      transform: translate(-100%, 0);
    }
    
    @include css(csstransforms, false) {
      left: -100%;
    }
    
    // Prevent the canvas from being too big, readjust the size above 37.5ems
    @media (min-width: 37.5em) {
      width: 50%;
    }
    
  }
  
  @if $canvas-direction == top-to-bottom {
    top: 0;
    width: 100%;
    
    @include css(csstransforms3d) {
      transform: translate3d(0, -100%, 0);
    }
    
    @include css(csstransforms3d, false) {
      transform: translate(0, -100%);
    }
    
    @include css(csstransforms, false) {
      top: -100%;
    }
    
  }
  
  // On active move the canvas into the viewport
  // This will reverse the transformation that is set by default
  .off-canvas-active & {
    top: 8.2em;
    // This resets our previous declaration
    pointer-events: auto;
    
    @include css(csstransforms3d) {
      transform: translate3d(0, 0, 0);
    }
    
    @include css(csstransforms3d, false) {
      transform: translate(0, 0);
    }
    
    @include css(csstransforms, false) {
      left: 0;
    }
    
  }
  
}

  .off-canvas__list {
    margin: 0;
    padding: 0;
    list-style: none;
  }

    .off-canvas__link {
      display: block;
      z-index: 2;
      padding: 2em;
      // If letter spacing is not declared as 0 then the transition will appear broken
      letter-spacing: 0;
      color: $accent;
      
      &:first-letter { 
        font-size: 2em; 
      }
      
      &:before {
        position: absolute;
        top: 0;
        left: 0;
        z-index: -1;
        width: 100%;
        height: 100%;
        content: '';
        transition: $general-transition-speed;
      }
      
      &:hover {
        letter-spacing: .2em;
        color: adjust-hue($accent, 30%);
        
        &:before {
          box-shadow: 
            inset .3em 0 0 0 $accent,
          		  inset .6em 0 0 0 $background,
            inset .7em 0 0 0 adjust-hue($accent, 20%);
        }
        
      }
      
    }


// ========================
// Main
// ========================

main { 
  overflow: hidden;
  perspective: 50em;
  transform-style: preserve-3d;
}

  section {
    transition: $canvas-transition-speed;
    
    .off-canvas-active & {
      
      @if $canvas-direction == left-to-right {
        transform-origin: right center;
      }
      
      @if $canvas-direction == top-to-bottom {
        transform-origin: center bottom;
      }
      
    }
    
    @if $content-push == traditional {
      
      .off-canvas-active & {
        
        @if $canvas-direction == left-to-right {
          
          @include css(csstransforms3d) {
            transform: translate3d(30%, 0, 0);
          }
          
          @include css(csstransforms3d, false) {
            transform: translate(30%);
          }
          
          @include css(csstransforms, false) {
            left: 30%;
          }
          
        }
        
        @if $canvas-direction == top-to-bottom {
          
          @include css(csstransforms3d) {
            transform: translate3d(0, 30%, 0);
          }
          
          @include css(csstransforms3d, false) {
            transform: translate(0, 30%);
          }
          
          @include css(csstransforms, false) {
            top: 30%;
          }
          
        }
        
      }
      
    }
    
    @if $content-push == scale {
      
      .off-canvas-active & {
        
        @include css(csstransforms) {
          transform: scale(.9);
        }
        
        @include css(csstransforms, false) {
          // Ideally the font size would decrease to match the scale property
          // Opacity was an idea that could feel similar
          opacity: .8;
        }
        
      }
      
    }
    
    @if $content-push == push-rotate {
      
      .off-canvas-active & {
        
        @if $canvas-direction == left-to-right {
          
          @include css(csstransforms3d) {
            transform: 
              translate3d(30%, 0, 0)
              rotate3d(0, 1, 0, -30deg);
          }
          
          @include css(csstransforms3d, false) {
            transform: 
              translate(30%)
              rotateY(-30deg);
          }
          
          @include css(csstransforms, false) {
            left: 30%;
          }
          
        }
        
        @if $canvas-direction == top-to-bottom {
          
          @include css(csstransforms3d) {
            transform: 
              translate3d(0, 30%, 0)
              rotate3d(1, 0, 0, 30deg);
          }
          
          @include css(csstransforms3d, false) {
            transform: 
              translate(0, 30%)
              rotateX(30deg);
          }
          
          @include css(csstransforms, false) {
            top: 30%;
          }
          
        }
        
      }
      
    }
    
  }
            
          
!
? ?
? ?
Must be a valid URL.
+ add another resource
via CSS Lint

JS

            
              $('.off-canvas-trigger').click(function() {
  $('body').toggleClass('off-canvas-active');
});
            
          
!
Must be a valid URL.
+ add another resource
via JS Hint
Loading ..................