A recreation of this "Gift Card" Dribbble shot by Chuan²: https://dribbble.com/shots/2045026-Gift-Card
Works best in Chrome (and browsers that support clip-path).
A Pen by David Khourshid on CodePen.
A recreation of this "Gift Card" Dribbble shot by Chuan²: https://dribbble.com/shots/2045026-Gift-Card
Works best in Chrome (and browsers that support clip-path).
A Pen by David Khourshid on CodePen.
| <div class="route" id="buy"></div> | |
| <section class="giftcard"> | |
| <section class="giftcard-cover"> | |
| <i class="fa fa-apple"></i> | |
| </section> | |
| <div class="giftcard-content"> | |
| <h2>Your order will be shipped to:</h2> | |
| <address> | |
| <h3>David Khourshid</h3> | |
| <a href="www.github.com/davidkpiano" target="_blank">www.github.com/davidkpiano</a> | |
| <a href="www.twitter.com/davidkpiano" target="_blank">www.twitter.com/davidkpiano</a> | |
| </address> | |
| <div class="subtext">Available to ship: 1 business day</div> | |
| </div> | |
| <footer class="giftcard-footer"> | |
| <div class="giftcard-text"> | |
| <h1>Gift Card</h1> | |
| <h2>$25.00</h2> | |
| </div> | |
| <div class="ribbon"> | |
| <div class="giftwrap"> | |
| <a href="#buy" class="button">Buy</a> | |
| </div> | |
| <div class="bow"> | |
| <i class="fa fa-bookmark"></i> | |
| <i class="fa fa-bookmark"></i> | |
| </div> | |
| </div> | |
| <div class="giftcard-info"> | |
| <div> | |
| <input type="text" name="" id="" placeholder="Enter a gift message" /> | |
| </div> | |
| <div> | |
| <a href="#" class="button secondary">Checkout</a> | |
| </div> | |
| </div> | |
| </footer> | |
| </section> | |
| @import url(http://fonts.googleapis.com/css?family=PT+Sans:400,700); | |
| *, *:before, *:after { box-sizing: border-box; position: relative; } | |
| $button-width: 100px; | |
| $button-height: 50px; | |
| $wrap-width: 32%; | |
| $wrap-height: 18%; | |
| $wrap-duration: 0.6s; | |
| $bow-top: 47%; | |
| $bow-left: 40%; | |
| $easing: cubic-bezier(0.77, 0, 0.175, 1); | |
| $ribbon-delay: $wrap-duration / 3; | |
| $wrap-delay: $wrap-duration * 1.2; | |
| $ribbon-color-foreground: #fed531; | |
| $ribbon-color-background: #db8b22; | |
| $card-width: 500px; | |
| $card-height: 300px; | |
| $color-primary: #cc199d; | |
| $color-gray: #939393; | |
| $footer-height: 5rem; | |
| html { | |
| height: 100%; | |
| width: 100%; | |
| background: #ececec; | |
| } | |
| body { | |
| height: 100%; | |
| width: 100%; | |
| margin: 0; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| } | |
| .route { | |
| display: none; | |
| } | |
| .giftcard { | |
| height: $card-height; | |
| width: $card-width; | |
| font-family: PT Sans, sans-serif; | |
| overflow: hidden; | |
| border-radius: 1.5rem/2rem; | |
| box-shadow: 8px 10px 16px rgba(0,0,0,0.1); | |
| transform: translateZ(0); | |
| } | |
| .giftcard-content, .giftcard-cover { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| height: calc(100% - #{$footer-height}); | |
| width: 100%; | |
| } | |
| .giftcard-cover { | |
| background: $color-primary; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| z-index: 2; | |
| > .fa-apple { | |
| color: white; | |
| font-size: 6rem; | |
| } | |
| } | |
| .giftcard-content { | |
| padding: 1rem 2rem; | |
| color: $color-gray; | |
| z-index: 1; | |
| background: white; | |
| > * { | |
| transform: translateX(3rem); | |
| opacity: 0; | |
| } | |
| h2 { | |
| font-size: 1.2rem; | |
| text-transform: uppercase; | |
| } | |
| h3 { | |
| font-size: 1rem; | |
| margin: 0; | |
| font-weight: normal; | |
| } | |
| h2, h3 { | |
| color: #232323; | |
| } | |
| div { font-size: 1rem; } | |
| address { | |
| font-style: normal; | |
| margin-bottom: 1rem; | |
| } | |
| a, .subtext { color: $color-gray; } | |
| a { | |
| display: block; | |
| text-decoration: none; | |
| } | |
| } | |
| .giftcard-footer { | |
| position: absolute; | |
| bottom: 0; | |
| left: 0; | |
| height: $footer-height; | |
| width: 100%; | |
| background: white; | |
| z-index: 3; | |
| transform: translateZ(0); | |
| > * { | |
| float: left; | |
| } | |
| } | |
| .giftcard-text, .giftcard-info { | |
| width: calc(100% - #{$button-width + $button-height}); | |
| padding: 1rem; | |
| } | |
| .giftcard-text { | |
| height: 100%; | |
| padding: 1rem; | |
| > h1, > h2 { | |
| margin: 0; | |
| font-weight: normal; | |
| line-height: 1.1; | |
| } | |
| h1 { | |
| font-size: 1.5rem; | |
| color: $color-primary; | |
| } | |
| h2 { | |
| font-size: 1.2rem; | |
| color: $color-gray; | |
| } | |
| } | |
| .giftcard-info { | |
| position: absolute; | |
| right: 0; | |
| top: 0; | |
| height: 100%; | |
| text-align: right; | |
| transform: translateX(100%); | |
| display: table; | |
| padding-left: 0; | |
| background: white; | |
| > * { | |
| display: table-cell; | |
| &:first-child { | |
| padding-right: 1rem; | |
| } | |
| } | |
| input[type="text"] { | |
| height: $button-height; | |
| width: 100%; | |
| padding: 0 1rem; | |
| -webkit-appearance: none; | |
| background: transparent; | |
| border: 1px solid #dedede; | |
| } | |
| } | |
| @mixin giftwrap($dx, $dy, $outer: true) { | |
| $coords: ( | |
| 50% - $dx $dx, | |
| 50% + $dx $dx, | |
| 100% - $dy 50% - $dy, | |
| 100% - $dy 50% + $dy, | |
| 50% + $dx 100% - $dx, | |
| 50% - $dx 100% - $dx, | |
| $dy 50% + $dy, | |
| $dy 50% - $dy | |
| ); | |
| $bgcoords: ( | |
| nth($coords, 1), | |
| 50% 2 * $dx, | |
| nth($coords, 2), | |
| nth($coords, 3), | |
| 100% - 2 * $dy 50%, | |
| nth($coords, 4), | |
| nth($coords, 5), | |
| 50% 100% - 2 * $dx, | |
| nth($coords, 6), | |
| nth($coords, 7), | |
| 2 * $dy 50%, | |
| nth($coords, 8), | |
| nth($coords, 7), | |
| nth($coords, 6), | |
| nth($coords, 5), | |
| nth($coords, 4), | |
| nth($coords, 3), | |
| nth($coords, 2), | |
| nth($coords, 1) | |
| ); | |
| @if not $outer { | |
| clip-path: polygon(#{join($coords, (), comma)}); | |
| } @else { | |
| clip-path: polygon(#{join($bgcoords, (), comma)}); | |
| } | |
| } | |
| $width: 100px; | |
| $height: 50px; | |
| .button, input[type="text"] { | |
| border-radius: 3px; | |
| } | |
| .button { | |
| display: inline-block; | |
| width: auto; | |
| height: $height; | |
| line-height: 50px; | |
| text-align: center; | |
| background: orange; | |
| color: white; | |
| font-size: 1.3rem; | |
| padding-left: 1rem; | |
| padding-right: 1rem; | |
| text-decoration: none; | |
| &.secondary { | |
| background: #009cee; | |
| } | |
| } | |
| .giftwrap { | |
| width: $width + $height; | |
| height: $width + $height; | |
| .button { | |
| width: $width; | |
| top: calc(50% - #{$height / 2}); | |
| left: calc(50% - #{$width / 2}); | |
| } | |
| &:before, &:after { | |
| display: none; | |
| content: ''; | |
| position: absolute; | |
| height: ($width + $height); | |
| width: ($width + $height); | |
| top: 0; | |
| left: 0; | |
| } | |
| &:before { | |
| @include giftwrap(0%, 0%); | |
| background: #fc1f33; | |
| z-index: 2; | |
| } | |
| &:after { | |
| @include giftwrap(0%, 0%, false); | |
| background: #bc0a13; | |
| z-index: -1; | |
| } | |
| } | |
| .bow { | |
| $bow-size: 1.25rem; | |
| display: none; | |
| opacity: 0; | |
| position: absolute; | |
| top: calc(#{$bow-top} - #{$bow-size / 2}); | |
| left: calc(#{$bow-left} - #{$bow-size / 2}); | |
| height: $bow-size; | |
| width: $bow-size; | |
| /* background: $ribbon-color-foreground; */ | |
| background: #000; | |
| border-radius: 50%; | |
| z-index: 3; | |
| &:after { | |
| content: ''; | |
| display: block; | |
| position: absolute; | |
| height: 100%; | |
| width: 100%; | |
| border-radius: 50%; | |
| background: lighten($ribbon-color-foreground, 10%); | |
| box-shadow: 0 1px 1px rgba(0,0,0,0.2); | |
| z-index: 2; | |
| } | |
| > .fa-bookmark { | |
| position: absolute; | |
| top: $bow-size / 2; | |
| left: $bow-size / 4; | |
| font-size: 1rem; | |
| color: $ribbon-color-foreground; | |
| text-shadow: 0 1px 1px rgba(0,0,0,0.2); | |
| z-index: 1; | |
| &:first-child { transform: translateX(-$bow-size / 2) scaleY(1.5) rotate(55deg); } | |
| &:last-child { transform: translateX($bow-size / 2) scaleY(1.5) rotate(-55deg); } | |
| } | |
| } | |
| @mixin ribbon($dx, $dy, $outer: true) { | |
| $width: 10%; | |
| $hw: $width / 2; | |
| $left: $bow-left; | |
| $top: $bow-top; | |
| $bgcoords: ( | |
| $left - $hw $dy, | |
| $left + $hw $dy, | |
| $left + $hw $top - $hw, | |
| 100% - $dx $top - $hw, | |
| 100% - $dx $top + $hw, | |
| $left + $hw $top + $hw, | |
| $left + $hw 100% - $dy, | |
| $left - $hw 100% - $dy, | |
| $left - $hw $top + $hw, | |
| $dx $top + $hw, | |
| $dx $top - $hw, | |
| $left - $hw $top - $hw | |
| ); | |
| $dy-top-inner: ($dy / $top) * ($dy + 5%); | |
| $dy-bottom-inner: 100% - $dy - ($dy / $top) * (100% - $top - $dy + 5%); | |
| $dx-left-inner: ($dx / $left) * (100% - $dx + 5%); | |
| $dx-right-inner: (1 - $dx / $left) * (100% - $dx); | |
| $coords: ( | |
| $left - $hw $dy + $dy-top-inner, | |
| nth($bgcoords, 1), | |
| nth($bgcoords, 2), | |
| $left + $hw $dy + $dy-top-inner, | |
| $dx-right-inner $top - $hw, | |
| nth($bgcoords, 4), | |
| nth($bgcoords, 5), | |
| $dx-right-inner $top + $hw, | |
| $left + $hw $dy-bottom-inner, | |
| nth($bgcoords, 7), | |
| nth($bgcoords, 8), | |
| $left - $hw $dy-bottom-inner, | |
| $dx-left-inner $top + $hw, | |
| nth($bgcoords, 10), | |
| nth($bgcoords, 11), | |
| $dx-left-inner $top - $hw, | |
| $left - $hw $dy + $dy-top-inner, | |
| $dx-left-inner $top - $hw, | |
| $dx-left-inner $top + $hw, | |
| $left - $hw $dy-bottom-inner, | |
| $left + $hw $dy-bottom-inner, | |
| $dx-right-inner $top + $hw, | |
| $dx-right-inner $top - $hw, | |
| $left + $hw $dy + $dy-top-inner | |
| ); | |
| @if not $outer { | |
| clip-path: polygon(#{join($bgcoords, (), comma)}); | |
| } @else { | |
| clip-path: polygon(#{join($coords, (), comma)}); | |
| } | |
| } | |
| .ribbon { | |
| width: $button-width + $button-height; | |
| height: $button-width + $button-height; | |
| top: calc(50% - #{($button-width + $button-height) / 2}); | |
| &:before, &:after { | |
| display: none; | |
| content: ''; | |
| position: absolute; | |
| width: $width + $height; | |
| height: $width + $height; | |
| top: 0; | |
| left: 0; | |
| } | |
| &:before { | |
| @include ribbon(25%, 35%, false); | |
| background: $ribbon-color-background; | |
| z-index: -1; | |
| } | |
| &:after { | |
| @include ribbon(0%, 0%, true); | |
| background: $ribbon-color-foreground; | |
| z-index: 2; | |
| } | |
| } | |
| #buy:target ~ .giftcard { | |
| .giftwrap > .button { | |
| animation: button 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.65) forwards; | |
| } | |
| .giftwrap { | |
| &:before, &:after { display: block; } | |
| &:before { animation: wrap-before-2 $wrap-duration $easing both; } | |
| &:after { animation: wrap-after-2 $wrap-duration $easing both; } | |
| } | |
| .bow { | |
| display: block; | |
| animation: bow 0.3s $wrap-duration * 1.2 cubic-bezier(0.175, 0.885, 0.32, 1.65) forwards; | |
| } | |
| .ribbon { | |
| &:before, &:after { display: block; } | |
| &:before { animation: ribbon-before $wrap-duration $ribbon-delay $easing both; } | |
| &:after { animation: ribbon-after $wrap-duration $ribbon-delay $easing both; } | |
| } | |
| .giftcard-footer { | |
| animation: footer $wrap-duration $wrap-delay $easing both; | |
| } | |
| .giftcard-cover { | |
| animation: cover $wrap-duration $wrap-delay $easing both; | |
| } | |
| .giftcard-content { | |
| > * { animation: content $wrap-duration $wrap-delay $easing both; } | |
| @for $i from 1 through 3 { | |
| > *:nth-child(#{$i}) { | |
| animation-delay: $wrap-delay + ($i - 1) * 0.05s; | |
| } | |
| } | |
| } | |
| } | |
| @keyframes button { | |
| to { transform: scale(0.9); } | |
| } | |
| @keyframes content { | |
| to { | |
| transform: translateX(0); | |
| opacity: 1; | |
| } | |
| } | |
| @keyframes cover { | |
| to { | |
| transform: translateY(calc(100% - 1px)) scaleX(0.95); | |
| } | |
| } | |
| @keyframes footer { | |
| to { | |
| transform: translateX(calc(-100% + #{$button-width + $button-height})); | |
| } | |
| } | |
| @keyframes wrap-before-2 { | |
| 50% { | |
| @include giftwrap(0%, 0%); | |
| } | |
| 100% { | |
| @include giftwrap($wrap-width, $wrap-height); | |
| } | |
| } | |
| @keyframes wrap-after-2 { | |
| 0% { | |
| clip-path: polygon(50% 40%, 60% 50%, 50% 60%, 40% 50%); | |
| } | |
| 49.999% { | |
| clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%); | |
| } | |
| 50% { | |
| @include giftwrap(0%, 0%, false); | |
| } | |
| 100% { @include giftwrap($wrap-width, $wrap-height, false); } | |
| } | |
| @keyframes ribbon-before { | |
| 0% { @include ribbon($wrap-height + 5%, $wrap-width + 5%, false); } | |
| 50% { @include ribbon(0%, 0%, false); } | |
| 100% { @include ribbon($wrap-height, $wrap-width, false); } | |
| } | |
| @keyframes ribbon-after { | |
| 0%, 50% { @include ribbon(0%, 0%, true); } | |
| 100% { @include ribbon($wrap-height, $wrap-width, true); } | |
| } | |
| @keyframes bow { | |
| from { transform: scale(0.8); opacity: 1; } | |
| to { transform: scale(1); opacity: 1; } | |
| } |
| <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet" /> |