Quantcast
Channel: 3D – Codrops
Viewing all 120 articles
Browse latest View live

BookBlock Revised

$
0
0

BookBlock Revised

View demo Download source

We’ve updated BookBlock, the content flip plugin. It has undergone some major changes with some improvements and we’ve added some new functionality. Take a look at the original article to see how to use it and what options are available.

Demos

We’ve updated the demos and added some different examples:

Summary of Changes

  • Removal of unnecessary and outdated prefixes in the CSS
  • Many styles that were added with JS before are now in the stylesheet. This allows for a better control.
  • We’ve added support for horizontal flipping (see demo 2)
  • We’ve added support for RTL (see demo 3)
  • We’ve added methods for going to the first and last page
  • There is a Vanilla JS version of the plugin

Caption Hover Effects

$
0
0

Caption Hover Effects

View demo Download source

Today we want to show you how to create some simple, yet stylish hover effects for image captions. The idea is to have a grid of figures and apply a hover effect to the items which will reveal a caption with the title, author and a link button. For some of the effects we will use 3D transforms. The aim is to keep the effects subtle and provide inspiration for many different variations.

Please note: this only works as intended in browsers that support the respective CSS properties.

The images used in the demos are Dribbble shots by talented Jacob Cummings.

Let’s get started.

The Markup

The structure of our grid and the figures will be made of an unordered list and each item will contain a figure element. The figure will contain an image and a figcaption with some text elements and a link:

<ul class="grid cs-style-1">
	<li>
		<figure>
			<img src="images/1.png" alt="img01">
			<figcaption>
				<h3>Camera</h3>
				<span>Jacob Cummings</span>
				<a href="http://dribbble.com/shots/1115632-Camera">Take a look</a>
			</figcaption>
		</figure>
	</li>
	<li>
		<figure>
			<!-- ... -->
		</figure>
	</li>
	<!-- ... -->
</ul>

This is the default structure for all the grid examples. Note that for effect 4 we will have an additonal division wrapping the image.
The class for each single effect will be added to the list; so example 1 will have “cs-style-1″, example 2 will have “cs-style-2″ and so on. That’s how we will define the effect styles for each single example.

But first let’s define the common styles for all effects.

The CSS

Note that the CSS will not contain any vendor prefixes, but you will find them in the files.

The common styles for all the figures is the following. First, we’ll define the styles for the grid and the list items that will serve as the containers of our figures:

.grid {
	padding: 20px 20px 100px 20px;
	max-width: 1300px;
	margin: 0 auto;
	list-style: none;
	text-align: center;
}

.grid li {
	display: inline-block;
	width: 440px;
	margin: 0;
	padding: 20px;
	text-align: left;
	position: relative;
}

Making the list items display as inline-blocks will allow us to center them be applying a centerd text-align to the parent.

Let’s reset the margins of the figure elements and set the position to relative. Our figcaption will be positioned absolutely, so we need to make sure it will do so inside of the figure:

.grid figure {
	margin: 0;
	position: relative;
}

The image will have a maximum width of 100% which will come in handy when we define a media query to resize the list items:

.grid figure img {
	max-width: 100%;
	display: block;
	position: relative;
}

The figcaption will be positioned absolutely. By default it will be positioned in the top left corner. We won’t define any width or height here as we will do so in all the individual styles:

.grid figcaption {
	position: absolute;
	top: 0;
	left: 0;
	padding: 20px;
	background: #2c3f52;
	color: #ed4e6e;
}

And finally, let’s define some styles for the text elements and the link:

.grid figcaption h3 {
	margin: 0;
	padding: 0;
	color: #fff;
}

.grid figcaption span:before {
	content: 'by ';
}

.grid figcaption a {
	text-align: center;
	padding: 5px 10px;
	border-radius: 2px;
	display: inline-block;
	background: #ed4e6e;
	color: #fff;
}

We’ll add the “by” for the span that contains the author name using the pseudo-class :before. Of course you can add that in the HTML, but this will give you the freedom to change it easily into something like “made by” or “Designer: ” or similar. Be careful not to remove meaning from your HTML, though, by doing something like this.

In the end of our CSS we will also add a media query for smaller screens:

@media screen and (max-width: 31.5em) {
	.grid {
		padding: 10px 10px 100px 10px;
	}
	.grid li {
		width: 100%;
		min-width: 300px;
	}
}

And now let’s start by doing some nice effects.

Note that we will use Modernizr to detect touch. But be aware that this is not 100% bulletproof for testing if you are on a touch device as pointed out here. We will replace the hover for the touch and add a class that will trigger the effects when we have detected touch. So you will always see another rule for that in addition to the :hover. We only want the hover to trigger when we don’t detect touch.

Effect 1

Caption Hover Effect 1

Let’s start with a very simple effect. We want the caption to fade in and move a bit to the right and down, creating the illusion of a 3D layer that comes out of the image.

For that we first need to set the width and height of the figcaption and set the initial opacity to 0:

.cs-style-1 figcaption {
	height: 100%;
	width: 100%;
	opacity: 0;
	text-align: center;
	backface-visibility: hidden;
	transition: transform 0.3s, opacity 0.3s;
}

We also add a transition and set the backface-visibility to hidden to avoid a jump in the text rendering in the end of the transition. You don’t have to use that if you don’t mind the little glitch.

On hover (or on touch) we will set the opacity to 1 and translate the figcaption a bit:

.no-touch .cs-style-1 figure:hover figcaption,
.cs-style-1 figure.cs-hover figcaption {
	opacity: 1;
	transform: translate(15px, 15px);
}

Additionally, we will position the text elements:

.cs-style-1 figcaption h3 {
	margin-top: 70px;
}

.cs-style-1 figcaption span {
	display: block;
}

.cs-style-1 figcaption a {
	margin-top: 30px;
}

Effect 2

CaptionHoverEffect2

This effect will move the image up and reveal the figcaption just like you can see on Minimamente from which it got inspired by.

So let’s add a transition for the transform to the image and make it move up on hover:

.cs-style-2 figure img {
	z-index: 10;
	transition: transform 0.4s;
}

.no-touch .cs-style-2 figure:hover img,
.cs-style-2 figure.cs-hover img {
	transform: translateY(-90px);
}

We’ve set the z-index to 10, so that the image stays on top of the caption.

The figcaption needs a fixed height and a width of 100%. We’ll stick it to the bottom of the figure:

.cs-style-2 figcaption {
	height: 90px;
	width: 100%;
	top: auto;
	bottom: 0;
}

Let’s also position the link button on the right side:

.cs-style-2 figcaption a {
	position: absolute;
	right: 20px;
	top: 30px;
}

Effect 3

CaptionHoverEffect3

A different approach to effect 2 is to hide any overflow when moving the image. Let’s do that and make it appear as if the caption is slightly pushing the image up.

First, we need to set the overflow of the figure to hidden. Like this we won’t see anything that spills out when moving around:

.cs-style-3 figure {
	overflow: hidden;
}

The image needs a transition for the transform and on hover we will translate it 50px up:

.cs-style-3 figure img {
	transition: transform 0.4s;
}

.no-touch .cs-style-3 figure:hover img,
.cs-style-3 figure.cs-hover img {
	transform: translateY(-50px);
}

The figcaption will be a bit higher than in the previous example and we will translate it out of the view of the figure. Let’s also add a transition for the transform and the opacity:

.cs-style-3 figcaption {
	height: 100px;
	width: 100%;
	top: auto;
	bottom: 0;
	opacity: 0;
	transform: translateY(100%);
	transition: transform 0.4s, opacity 0.1s 0.3s;
}

On hover we’ll set to opacity to 1 and translate it up. See how we have added two transitions? One for the normal state and one for the hover? This is how we can control what happens when we hover and when we hover out. The transition here will be applied on hover: we want the element to become opaque quickly while taking 0.4 seconds for the transform. When we hover out, the opacity will be set again to 0 but only after a delay of 0.3 seconds. This will make the effect look consistent and natural.

.no-touch .cs-style-3 figure:hover figcaption,
.cs-style-3 figure.cs-hover figcaption {
	opacity: 1;
	transform: translateY(0px);
	transition: transform 0.4s, opacity 0.1s;
}

Let’s not forget about our link button:

.cs-style-3 figcaption a {
	position: absolute;
	bottom: 20px;
	right: 20px;
}

Effect 4

CaptionHoverEffect4

The forth example will make use of some 3D goodness. The aim is to flip the caption from the left side and push the image to the right.

We will use the list item as a perspective container so that we can play around with 3D transforms:

The CSS

.cs-style-4 li {
	perspective: 1700px;
	perspective-origin: 0 50%;
}

The child needs to have the following transform-style if we want the 3D transforms to work in the other elements:

.cs-style-4 figure {
	transform-style: preserve-3d;
}

As mentioned earlier, this example is going to have another wrapper for the image, Why do we need this? Well, we need to set the image’s parent to overflow hidden, because we don’t want to see the image spilling out of the container when we move it. We could set the overflow of the figure to hidden but then we won’t see the beautiful 3D effect of the caption. So, let’s add another wrapper and set it to overflow hidden instead:

.cs-style-4 figure > div {
	overflow: hidden;
}

Let’s move the image on hover:

.cs-style-4 figure img {
	transition: transform 0.4s;
}

.no-touch .cs-style-4 figure:hover img,
.cs-style-4 figure.cs-hover img {
	transform: translateX(25%);
}

The figcaption will have half of the width of the figure and we’ll set its initial opacity to 0. Now, let’s rotate it 90 degrees on the Y-axis which will make it be flipped towards us with the origin on its left side. We would basically not see it like that. Let’s set a transition for the “hover out” which will work in the same principle like described in the previous example:

.cs-style-4 figcaption {
	height: 100%;
	width: 50%;
	opacity: 0;
	backface-visibility: hidden;
	transform-origin: 0 0;
	transform: rotateY(-90deg);
	transition: transform 0.4s, opacity 0.1s 0.3s;
}

On hover we will fade it in and rotate it to 0 degrees, making it flip like a page of a book from the left side:

.no-touch .cs-style-4 figure:hover figcaption,
.cs-style-4 figure.cs-hover figcaption {
	opacity: 1;
	transform: rotateY(0deg);
	transition: transform 0.4s, opacity 0.1s;
}

Last, but not least, our little link button:

.cs-style-4 figcaption a {
	position: absolute;
	bottom: 20px;
	right: 20px;
}

Effect 5

CaptionHoverEffect5

This effect will make the image shrink and scale the caption in from the back.

Let’s put the image on top of the caption and add a transition for the transform:

.cs-style-5 figure img {
	z-index: 10;
	transition: transform 0.4s;
}

On hover, we want to scale the image down:

.no-touch .cs-style-5 figure:hover img,
.cs-style-5 figure.cs-hover img {
	transform: scale(0.4);
}

The caption will initially scaled to 0.7 and faded out:

.cs-style-5 figcaption {
	height: 100%;
	width: 100%;
	opacity: 0;
	transform: scale(0.7);
	backface-visibility: hidden;
	transition: transform 0.4s, opacity 0.4s;
}

On hover, we will scale it up and fade it in:

.no-touch .cs-style-5 figure:hover figcaption,
.cs-style-5 figure.cs-hover figcaption {
	transform: scale(1);
	opacity: 1;
}

Super-easy. Oh, and of course, the little link button wants to be in the bottom right corner:

.cs-style-5 figure a {
	position: absolute;
	bottom: 20px;
	right: 20px;
}

Effect 6

CaptionHoverEffect6

This effect is a variation of effect 5. There are many possibilities to play around with this type of effect, think about positioning the image in a different place and showing some more text. This effect will position the text and the image in a different place than before and we will not fade the caption in or scale it, it will already be there, creating a different “environment”.

So, let’s again do the same thing for the image, just that on hover we will also translate it up a bit:

.cs-style-6 figure img {
	z-index: 10;
	transition: transform 0.4s;
}

.no-touch .cs-style-6 figure:hover img,
.cs-style-6 figure.cs-hover img {
	transform: translateY(-50px) scale(0.5);
}

So, no transition for the caption this time:

.cs-style-6 figcaption {
	height: 100%;
	width: 100%;
}

And let’s position the text elements:

.cs-style-6 figcaption h3 {
	margin-top: 60%;
}

.cs-style-6 figcaption a {
	position: absolute;
	bottom: 20px;
	right: 20px;
}

Effect 7

CaptionHoverEffect7

The last effect in this tutorial will “grow” the caption from behind the image, making it look like a frame.

Since the frame of the first elements will be overlapping the other list items, we have to make sure that the z-indexes are correct (reversed):

.cs-style-7 li:first-child { z-index: 6; }
.cs-style-7 li:nth-child(2) { z-index: 5; }
.cs-style-7 li:nth-child(3) { z-index: 4; }
.cs-style-7 li:nth-child(4) { z-index: 3; }
.cs-style-7 li:nth-child(5) { z-index: 2; }
.cs-style-7 li:nth-child(6) { z-index: 1; }

Just like in the previous examples, we want the image to be on top of the caption:

.cs-style-7 figure img {
	z-index: 10;
}

The caption will be 100% of the figure and we’ll set the transition for the opacity, height and box-shadow. Why the box shadow? We can easily use the box shadow to create a frame around the caption:

.cs-style-7 figcaption {
	height: 100%;
	width: 100%;
	opacity: 0;
	backface-visibility: hidden;
	box-shadow: 0 0 0 0px #2c3f52;
	transition: opacity 0.3s, height 0.3s, box-shadow 0.3s;
}

On hover we will set the opacity to 1, increase the height and set the box shadow’s spread to 10 pixels:

.no-touch .cs-style-7 figure:hover figcaption,
.cs-style-7 figure.cs-hover figcaption {
	opacity: 1;
	height: 130%;
	box-shadow: 0 0 0 10px #2c3f52;
}

Let’s position the text elements. We want the elements to appear just after we animated the caption’s height but when we “hover out”, we want them to disappear immediately. So we’ll set the transition-duration to 0 seconds for the normal state.

.cs-style-7 figcaption h3 {
	margin-top: 86%;
}

.cs-style-7 figcaption h3,
.cs-style-7 figcaption span,
.cs-style-7 figcaption a {
	opacity: 0;
	transition: opacity 0s;
}

.cs-style-7 figcaption a {
	position: absolute;
	bottom: 20px;
	right: 20px;
}

On hover we will make all elements appear with a delay:

.no-touch .cs-style-7 figure:hover figcaption h3,
.no-touch .cs-style-7 figure:hover figcaption span,
.no-touch .cs-style-7 figure:hover figcaption a,
.cs-style-7 figure.cs-hover figcaption h3,
.cs-style-7 figure.cs-hover figcaption span,
.cs-style-7 figure.cs-hover figcaption a {
	transition: opacity 0.3s 0.2s;
	opacity: 1;
}

And that’s it! I hope you enjoyed this tutorial and got inspired to create many cool caption hover effects.

View demo Download source

Nifty Modal Window Effects

$
0
0

ModalWindowEffects

View demo Download source

Today we want to share some ideas for modal window effects with you. There are infinite possibilities for transitioning the appearance of a dialog box and we wanted to provide some ideas of how to show dialog boxes and provide some inspiration.

The idea is to have a trigger button (or any element) which will make a modal window appear on click using a simple transition (or animation).

Please note: this only works as intended in browsers that support the respective CSS
properties. Modern browsers only!

There are some knows issue with using visibility/opacity for iOS < 6 Mobile Safari, so this probably won't work on older devices.

The structure of the modal window consists of a main wrapper and a content division:

<div class="md-modal md-effect-1" id="modal-1">
	<div class="md-content">
		<h3>Modal Dialog</h3>
		<div>
			<p>This is a modal window. You can do the following things with it:</p>
			<ul>
				<li><strong>Read:</strong> Modal windows will probably tell you something important so don't forget to read what it says.</li>
				<li><strong>Look:</strong> modal windows enjoy a certain kind of attention; just look at it and appreciate its presence.</li>
				<li><strong>Close:</strong> click on the button below to close the modal.</li>
			</ul>
			<button class="md-close">Close me!</button>
		</div>
	</div>
</div>

...

<div class="md-overlay"></div>

The main wrapper is used as a container that will simply be shown or hidden (with visibility, using the class “md-show”) and the inner content will have the transition. The overlay is placed after the modal(s), so we can control the appearance using the adjacent sibling selector:

.md-modal {
	position: fixed;
	top: 50%;
	left: 50%;
	width: 50%;
	max-width: 630px;
	min-width: 320px;
	height: auto;
	z-index: 2000;
	visibility: hidden;
	backface-visibility: hidden;
	transform: translateX(-50%) translateY(-50%);
}

.md-show {
	visibility: visible;
}

.md-overlay {
	position: fixed;
	width: 100%;
	height: 100%;
	visibility: hidden;
	top: 0;
	left: 0;
	z-index: 1000;
	opacity: 0;
	background: rgba(143,27,15,0.8);
	transition: all 0.3s;
}

.md-show ~ .md-overlay {
	opacity: 1;
	visibility: visible;
}

For some effects we will also add a class to the html element. We want this for creating some 3D effects on the body and the content. Note that we are assuming that all the content of the page (except the modal and the overlay) are wrapped in a container:

.md-perspective,
.md-perspective body {
	height: 100%;
	overflow: hidden;
}

.md-perspective body  {
	background: #222;
	perspective: 600px;
}

.container {
	background: #e74c3c;
	min-height: 100%;
}

To be able to control each effect, we use an additional effect class to define what kind of transition we want for that specific modal window. An example for an individual effect is the following:

/* Effect 5: newspaper */
.md-show.md-effect-5 ~ .md-overlay {
	background: rgba(0,127,108,0.8);
}

.md-effect-5 .md-content {
	transform: scale(0) rotate(720deg);
	opacity: 0;
	transition: all 0.5s;
}

.md-show.md-effect-5 .md-content {
	transform: scale(1) rotate(0deg);
	opacity: 1;
}

The trigger buttons will have a data-attribute that holds the reference to the modal box that we want to show:

<button class="md-trigger" data-modal="modal-5">Newspaper</button>

For the special perspective cases, we’ll also add the class “md-setperspective” to the trigger button.

With JavaScript we’ll simple add the class “md-show” to the respective modal when we click on a button, and, if indicated, the “md-perspective” class to the html element.

To experiment with new effects, add a new button and a new modal with an effect class and an ID, referencing to that ID in the button’s data-attribute “data-modal”. Then you can add another set of styles for that specific effect.

If you only want the effect/transition to happen when the modal window appears, but not when it disappears, just add the transition to the “.md-show.md-effect-x .md-content” declaration (like we did for some of the examples).

For the background blur effect we are using Polyfilter by Christian Schaefer to support older browsers.

I hope you enjoyed these little effect ideas and find them inspiring!

View demo Download source

Animated Books with CSS 3D Transforms

$
0
0

AnimatedBooks

View demo Download source

In this playground we’ll show you some creative, animated books with CSS 3D transforms and transitions.
We’ll show you two types of book designs: hardcover and paperback. Both were made to be easily modifiable in some of their content parts using CSS, images, anchors and some extra little details :)

Please note: this only works as intended in browsers that support the respective CSS properties.

Hardcover Book

AnimatedBooks_01

The hardcover book consists of three cubes: hardcover front, book spine and hardcover back. Each part uses pseudo-elements to provide some thickness.

cubes

Paperback

AnimatedBooks_02

In contrast to the hardcover, the paperback is a bit simpler. It is made from flat surfaces like the pages and does not include a book spine: paperback front, ruled paper and paperback back

:hover effects

For both books I use the technique of transitioning on “hover on” and “hover off” which is achieved by simply defining the “hover on” transition in the :hover class and the “hover off” transition in the original class declaration of the respective element.

Hover on

When we opened the book, the cover changes from “z-index: 100;” to 0.
The pages have different transition durations, which creates a smooth opening.


.book:hover > .hardcover_front {
	transform: rotateY(-145deg) translateZ(0);
	z-index: 0;
}

.book:hover > .page li:nth-child(1) {
	transform: rotateY(-30deg);
	transition-duration: 1.5s;
}

.book:hover > .page li:nth-child(2) {
	transform: rotateY(-35deg);
	transition-duration: 1.8s;
}

.book:hover > .page li:nth-child(3) {
	transform: rotateY(-118deg);
	transition-duration: 1.6s;
}

.book:hover > .page li:nth-child(4) {
	transform: rotateY(-130deg);
	transition-duration: 1.4s;
}

.book:hover > .page li:nth-child(5) {
	transform: rotateY(-140deg);
	transition-duration: 1.2s;
}

Hover off

When we close the book, we can avoid the overlapping of the pages on the cover by reducing the transition duration of the pages.


.hardcover_front{
	transition: all 0.8s ease, z-index 0.6s;
}

.page > li {
	width: 100%;
	height: 100%;
	transform-origin: left center;
	transition-property: transform;
	transition-timing-function: ease;
}

.page > li:nth-child(1) {
	transition-duration: 0.6s;
}

.page > li:nth-child(2) {
	transition-duration: 0.6s;
}

.page > li:nth-child(3) {
	transition-duration: 0.4s;
}

.page > li:nth-child(4) {
	transition-duration: 0.5s;
}

.page > li:nth-child(5) {
	transition-duration: 0.6s;
}

Cover Design

The cover design is pretty straightforward; I’ve added the class “coverDesign” as an initial configuration and a second class for backgrounds or images.

An alternative of placing an image on the cover is the following:

<img src="" width="100%" height="100%"></img>

To add a little red ribbon to the front cover, simply add:

<span class="ribbon"></span>

And that’s it! I hope it’s useful and inspiring!

View demo Download source

On Scroll Header Effects

$
0
0

Header Effects

View demo Download source

You’ve surely seen those really cool on scroll effects for headers that have been around lately. One example is the header on the Riot Industries website by Phil Renaud which rotates in 3d on click and enlarges when scrolling down. Similar work has been done by Johnny Simpson where he explores Scroll Activated Fixed Header Animations. We’ve also created a Blueprint for an On-Scroll Animated Header to get you started.

Today we’d like to give you some inspiration for animated headers and show you what kind of effects could be used to spice up your website’s starting element and give it some life.

Please note: this only works as intended in browsers that support the respective CSS properties. Modern browsers only!

The demo for the effects serves as inspiration only and we’ve used a technique that involves changing the state classes of the header which would of course be customized depending on which effect would like to be used. It’s important to understand that the states depend on each other, i.e. changing from class A to class B does something (using transitions) and going from A to C might not cause the desired effect. So the order matters in this example that tries to show all the effects on one page.

Also note that scrolling super fast might cause a jump from the beforementioned class A to class C which might not always look very fancy.

In the demo we use the fantastic jQuery Waypoints plugin by Caleb Troughton.

The header is composed of various parts for showcasing all the effects. It has a perspective wrapper, a front and a bottom (for the 3d rotation):

<header id="ha-header" class="ha-header ha-header-large">
	<div class="ha-header-perspective">
		<div class="ha-header-front">
			<h1><span>Header Effects</span></h1>
			<nav>
				<a>‹ Previous Demo</a>
				<a>Something</a>
				<a>Anything</a>
				<a>Back to the article</a>
			</nav>
		</div>
		<div class="ha-header-bottom">
			<nav>
				<a>Dalliance</a>
				<a>Inglenook</a>
				<a>Lagniappe</a>
				<a>Mellifluous</a>
				<a>Erstwhile</a>
				<a>Wafture</a>
				<a>Serendipity</a>
				<a>Love</a>
			</nav>
		</div>
	</div>
</header>

We add a special class to the sections which will trigger the class change:

<section class="ha-waypoint" data-animate-down="ha-header-small" data-animate-up="ha-header-large">
	<!-- ... -->
</section>

The data atrributes are used for setting the right classes depending on which direction we are scrolling. In our demo the animate-up data attribute contains the class of the previous animate-down one.

An example for a state class is the following “rotate” one:

.ha-header-rotate {
	height: 220px;
	top: 50px;
	padding-left: 50px;
	padding-right: 50px;
}

.ha-header-rotate .ha-header-front {
	transform: translateY(-100%) rotateX(90deg);
}

.ha-header-rotate .ha-header-bottom {
	top: 50%;
	transition: transform 0.5s;
	transform: rotateX(0deg) translateY(-100%);
}

The state classes are applied to the header element and from there we can define some changes for the children.

With the help of the Waypoints plugin we simply add the respective classes:

var $head = $( '#ha-header' );
$( '.ha-waypoint' ).each( function(i) {
	var $el = $( this ),
		animClassDown = $el.data( 'animateDown' ),
		animClassUp = $el.data( 'animateUp' );

	$el.waypoint( function( direction ) {
		if( direction === 'down' && animClassDown ) {
			$head.attr('class', 'ha-header ' + animClassDown);
		}
		else if( direction === 'up' && animClassUp ){
			$head.attr('class', 'ha-header ' + animClassUp);
		}
	}, { offset: '100%' } );
} );

We hope you enjoy the effects and that they give you some inspiration on how to make a fancy animated header.

View demo Download source

3D Effect for Mobile App Showcase

$
0
0

appshowcase3d

View demo Download source

Today we’d like to share an experimental 3D effect with you. It involves a 3D mobile device and some mobile app screenshots. When clicking on a toggle button, we’ll animate the mobie device to rotate and we’ll move each screen so that we have a layered view in the end. You have surely seen this kind of presentation of apps before and we thought it might be fun to do it in CSS.

Please note: this only works as intended in browsers that support the respective CSS properties. Modern browsers only!

The idea is to position the mobile device with an slight initial rotation:

appshowcase3d_1

Then we apply a class to the wrapper which will make the device transition to a second position where the screens move out in a layer stack. Effect one is the following:

appshowcase3d_2

The second effect has a different rotation:

appshowcase3d_3

And the third one will also show some labels:

appshowcase3d_4

The screens are anchors so that one can actually link them to eventual info pages. There are a lot of possibilities here, go nuts.

There is a SCSS file included for dealing with some dimension variables of the device and some other variables.

The 3D phone includes a technique for the rounded corners involving pseudo elements for the sides, first implemented by brilliant web designer and developer Jonathan Levaillant.

We hope you enjoy the effects and that they give you some inspiration.

View demo Download source

3D Shading with Box-Shadows

$
0
0

3DShadingWithBoxShadows

View demo Download source

When working with 3D transformed elements, you might notice that they don’t have any shading and appear to be very flat. In real life, objects block light and have shadows. Surfaces can be matte, reflective, and everything in between. Indeed, we can do better.

If you need to cast light onto complicated geometry, there are options available such as Photon, but they’re very processor intensive. In this article, I’ll show you a solution that can be applied to objects that only have a few faces. Our example will be a 3D movie gallery with glossy posters and, when the posters are rotated, the sides will contain matte information cards with meta data about the film.

The Markup

Our page is going to have a few different parts. First, we need a simple wrapper to center everything on the page. Next, we’ll create an unordered list that will contain all of our 3D posters. We’ll add the class “stage” to the ul and “scene” to each li. In our CSS, the stage element will act as a container for the scene elements, which will be their own 3D environment with the perspective property applied.


<div class="wrapper">
  <ul class="stage">
    <li class="scene"></li>
    <li class="scene"></li>
    <li class="scene"></li>
  </ul> 
</div>

For each li, we need to add quite a bit of markup. This will contain our movie poster as well as all the metadata about each movie. In a more robust movie library, this could be done dynamically with some backend code. We’ll keep things simple for the purposes of this example.


<li class="scene">
  <div class="movie">
    <div class="poster"></div>
    <div class="info">
      <header>
        <h1>It's a Wonderful Life</h1>
        <span class="year">1946</span>
        <span class="rating">PG</span>
        <span class="duration">130 minutes</span>
      </header>
      <p>
        In Bedford Falls, New York on Christmas Eve, George Bailey is deeply troubled. Prayers for his well-being from friends and family reach Heaven. Clarence Odbody, Angel Second Class, is assigned to visit Earth to save George, thereby earning his wings. Franklin and Joseph, the head angels, review George's life with Clarence.
      </p>
    </div>
  </div>
</li>

Our library will contain two more movies in addition to this one. The metadata is a bit lengthy and there are also a few image assets you’ll need, but everything is included in the code download. Let’s get to styling.

3DShadingWithBoxShadows_01

The CSS

Note that the CSS will not contain any vendor prefixes, but you will find them in the files.

First, let’s get some of the basics out of the way. We need to center our wrapper and then remove the default list styling from the stage class.

.wrapper {
	margin: 0 auto 100px auto;
	max-width: 960px;
}

.stage {
	list-style: none;
	padding: 0;
}

Next, we want to style the scene class with an explicit width and height (the same as our posters). If you’d like to provide additional detail needed for high resolution displays then you could use images that are twice as large.

The margin between each scene will provide sufficient spacing so that they don’t overlap each other. Then we’ll float all of the list items to the left so that they line up next to one another in a nice gallery. This is similar to how most top-level website navigation is created.

Finally, we’ll add the perspective property. This will allow us to create a 3D scene in the nested elements, and the value of 1000px will give the objects a decent amount of depth. A lower value would be a bit too dramatic, but you can experiment with this and see what works best for you.

.scene {
	width: 260px;
	height: 400px;
	margin: 30px;
	float: left;
	perspective: 1000px;
}

Similar .scene, we also need to set an explicit width and height on .movie. This will help each poster look correct when it’s being transformed. Next, we’ll set the transform-style to preserve-3d so that we can transform elements in 3D space. Finally, we’ll translate it along the Z plane by -130 pixels. This will give the posters a little bit more room to move around and really pop towards the viewer.

.movie {
	width: 260px;
	height: 400px;
	transform-style: preserve-3d;
	transform: translateZ(-130px);
	transition: transform 350ms;
}

Here’s where the movement happens. We’ll apply a transition to the .movie class. The transition timing is set to a rapid 350ms, but if you’d like a more dramatic effect, you could slow it down.

Then we’ll transform each .movie on :hover. This will rotate the 3D poster along the Y axis and then move it towards the screen along the Z plane. You could rotate the poster by a full 90 degrees, but I prefer to leave it slightly offset to maintain the 3D effect while hovered.

.movie:hover {
	transform: rotateY(-78deg) translateZ(20px);
}

Observant coders will notice that, while we have translated the scene, we never actually rotated any elements that would give semblance of geometry and build an object. Let’s create each 3D poster now. Each .poster and .info card needs to be positioned absolutely, otherwise they’ll push one another out of the way. We don’t want that, because we’re going to position them using transforms. Next, we need to set an explicit dimensions on both of the classes so that each of the two sides is exactly the same.

.movie .poster, 
.movie .info {
  position: absolute;
  width: 260px;
  height: 400px;
  background-color: #fff;
  backface-visibility: hidden;
}

With the geometry of our posters ready, we can transform them into place. The .poster just needs to be moved 130px along the Z plane (because remember, we moved the .movie back by this amount). The background size has been set to cover so that when we apply our poster backgrounds, they’ll fill the geometry. They should anyway since they’re sized correctly, so this is really just a precautionary measure.

The .info needs to be translated by the same amount as the .poster, but it also needs to be rotated. We want to form a square box, so we’ll rotate it 90 degrees. I’ve added some styling after the transformation, but this is mostly just for aesthetic reasons.

.movie .poster  {
  transform: translateZ(130px);
  background-size: cover;
  background-repeat: no-repeat;
}

.movie .info {
  transform: rotateY(90deg) translateZ(130px);
  border: 1px solid #B8B5B5;
  font-size: 0.75em;
}

We’ll use the pseudo-element ::after to create another face that will have a subtle box shadow beneath the movie box:

.movie::after {
  content: '';
  width: 260px;
  height: 260px;
  position: absolute;
  bottom: 0;
  box-shadow: 0 30px 50px rgba(0,0,0,0.3);
  transform-origin: 100% 100%;
  transform: rotateX(90deg) translateY(130px);
  transition: box-shadow 350ms;
}

.movie:hover::after {
  box-shadow: 20px -5px 50px rgba(0,0,0,0.3);
}

Further down in the CSS, we style the metadata contained inside the .info class. None of this is particularly relevant to this demo, as it’s mostly just formatting some text and imagery. The real magic happens later on.

.info header {
  color: #FFF;
  padding: 7px 10px;
  font-weight: bold;
  height: 195px;
  background-size: contain;
  background-repeat: no-repeat;
  text-shadow: 0px 1px 1px rgba(0,0,0,1);
}

.info header h1 {
  margin: 0 0 2px;
  font-size: 1.4em;
}

.info header .rating {
  border: 1px solid #FFF;
  padding: 0px 3px;
}

.info p {
  padding: 1.2em 1.4em;
  margin: 2px 0 0;
  font-weight: 700;
  color: #666;
  line-height: 1.4em;
  border-top: 10px solid #555;
}

Here’s where we create our pseudo-lighting using the box-shadow property. For the .poster class, we add an inset box shadow with an X and Y offset of 0px. The blur radius will be set to 40px and the shadow is set to rgba(255,255,255,0) (which is white “shadow” set to 100% transparency). Remember, there’s a transition applied to all the children of .movie, so if we set a starting state for the shadow, we can then animate it using a :hover state.

If we :hover over the .movie, it will reset the values of the box-shadow for the .poster and animate them with a transition. In this new state, the poster is still inset, but this time it has an X offset of 300px and an opacity of 0.8 for the white color. This will effectively move the box-shadow over top the poster with some fuzziness along the edge. The transparency will help to gel the shadow with the poster image, which will make the poster look like it has a glossy finish.

.movie .poster,
.movie .info,
.movie .info header {
  transition: box-shadow 350ms;
}

.movie .poster {
  box-shadow: inset 0px 0px 40px rgba(255,255,255,0);
}

.movie:hover .poster {
  box-shadow: inset 300px 0px 40px rgba(255,255,255,0.8);
}

Just like for the poster, we also want to apply a shadow to the other side of the box. For the .info panel, we want a dark shadow to disappear as the element is rotating forward and then reappear when the paper texture recedes back into the gap between each 3D poster. On our page, with the glossy poster on the left and the shadow on the right, it will make it appear as though there’s a light source coming from the left side of the page.


.movie .info, 
.movie .info header {
  box-shadow: inset -300px 0px 40px rgba(0,0,0,0.5);
}

.movie:hover .info, 
.movie:hover .info header {
  box-shadow: inset 0px 0px 40px rgba(0,0,0,0);
}

Last but not least, we need to add the poster images and still preview images to each movie. I’ve done this using the :nth-child pseudo class, but again, this would probably be done elsewhere in a dynamic website.

.scene:nth-child(1) .movie .poster {
  background-image: url(../img/poster01.jpg);
}

.scene:nth-child(2) .poster {
  background-image: url(../img/poster02.jpg);
}

.scene:nth-child(3) .poster {
  background-image: url(../img/poster03.jpg);
}

.scene:nth-child(1) .info header {
  background-image: url(../img/still01.jpg);
}

.scene:nth-child(2) .info header {
  background-image: url(../img/still02.jpg);
}

.scene:nth-child(3) .info header {
  background-image: url(../img/still03.jpg);
}

You’ll notice that we’ve used Modernizr in the demo to detect support for 3D transforms and provide a simple fallback for browsers that don’t support it.

That’s it! As I suggested in the intro, this technique can be applied to simple geometry. Some of you may be wondering why I didn’t use a gradient to create a more controlled shadow over top the poster images. At the time of this article, transitions cannot be applied to gradients, so while this might work for static geometry, the illusion would be broken as soon as the element is animated.

If you have any questions, comments, or improvements on this technique, I’d love to hear about them in the comments!

View demo Download source

Transitions for Off-Canvas Navigations

$
0
0

sidebartransitions

View demo Download source

Today we’d like to share another set of transition effects with you. This time we’ll explore transitions for sidebars or off-canvas content like the one we’ve used in the Multi-Level Push Menu. The idea is to show some hidden sidebar with a subtle transition on the element itself and also on the remaining content. Usually the sidebar slides in, pushing the other content to the side. But there are many more possibilities for subtle and fancy effects and today we want to give you some inspiration.

The structure of our demo is very specific because we want to be able to show all effects in one page only. But in general, we need a sidebar element that will be either inside or outside of a push wrapper, depending on whether we want the sidebar to be on top of the push wrapper or under it.
So, either we’ll have

<div id="st-container" class="st-container">

	<!-- content push wrapper -->
	<div class="st-pusher">

		<nav class="st-menu st-effect-1" id="menu-1">
			<!-- sidebar content -->
		</nav>

		<div class="st-content"><!-- this is the wrapper for the content -->
			<div class="st-content-inner"><!-- extra div for emulating position:fixed of the menu -->
				<!-- the content -->
			</div><!-- /st-content-inner -->
		</div><!-- /st-content -->

	</div><!-- /st-pusher -->

</div><!-- /st-container -->

or

<div id="st-container" class="st-container">

	<nav class="st-menu st-effect-1" id="menu-1">
		<!-- sidebar content -->
	</nav>

	<!-- content push wrapper -->
	<div class="st-pusher">

		<div class="st-content"><!-- this is the wrapper for the content -->
			<div class="st-content-inner"><!-- extra div for emulating position:fixed of the menu -->
				<!-- the content -->
			</div><!-- /st-content-inner -->
		</div><!-- /st-content -->

	</div><!-- /st-pusher -->

</div><!-- /st-container -->

An example effect is the following. We add a perspective value to the main container and then we rotate the push wrapper and the menu in 3D:

.st-effect-7.st-container {
	perspective: 1500px;
	perspective-origin: 0% 50%;
}

.st-effect-7 .st-pusher {
	transform-style: preserve-3d;
}

.st-effect-7.st-menu-open .st-pusher {
	transform: translate3d(300px, 0, 0);
}

.st-effect-7.st-menu {
	transform: translate3d(-100%, 0, 0) rotateY(-90deg);
	transform-origin: 100% 50%;
	transform-style: preserve-3d;
}

.st-effect-7.st-menu-open .st-effect-7.st-menu {
	visibility: visible;
	transform: translate3d(-100%, 0, 0) rotateY(0deg);
}

Note that we’re only using visibility here because we have more than one sidebar in our demo. If you just have one sidebar, you won’t have to set the visibility value from hidden to visible.

Some browsers don’t support transitions on pseudo-elements (our overlays), so you might see a quick flicker in those browsers (e.g. some mobile browsers).

IE10 does not support transform-style: preserve-3d which will break nested 3D transformed elements. We use this in a couple of examples, so you won’t be able to see the effect correctly for those ones.

SidebarTransitions_01

For the demos we are using the beautiful Linicons iconfont by Sergey Shmidt created with the help of the IcoMoon app.

We hope this collection gives you some inspiration for creating some nice effects.

I hope you enjoyed these sidebar transitions and find them inspiring!

View demo Download source


Animated Opening Type

$
0
0

OpeningType

View demo Download source

In this tutorial I’m going to explain how to achieve an interesting 3D opening type effect with CSS based on the one I previously created. My experiment was actually inspired by Edenspiekermann’s Open Type project for the Kröller-Müller Museum, a dynamic concept that plays with light and shadow in a simple but incredibly creative way. The aim of this tutorial is to show how we can bring some life to letters using CSS transforms and transitions on pseudo-elements with a technique that will allow to open a letter from all four sides.

Please note that pseudo-element transitions don’t work in every browser. Best viewed in Chrome and Firefox.

The Markup

The markup needed is pretty simple, just a span that contains the character, but since we’re going to work with generated content we must add a custom data-attribute for repeating the text of each letter. We’ll also use a grid as our main wrapping structure where each letter will be inside of a list item. So, each list item will have a specific direction class for the letter:

<ul class="grid">
	<li class="ot-letter-left"><span data-letter="C">C</span></li>
	<li class="ot-letter-top"><span data-letter="J">J</span></li>
	<li class="ot-letter-right"><span data-letter="8">8</span></li>
	<li class="ot-letter-bottom"><span data-letter="A">A</span></li>
</ul>

The CSS

Let’s add some basic styles to the letter span. There will be three elements to our letter: the dark bottom part that makes the background seem cut out, the opening piece and the shadow that appears when we open the letter. This span that we are styling now, is the bottom part. We’ll add the perspective property to the span so that we can have a nice three-dimensional effect on the pseudo elements.

.grid li span {
	display: inline-block;
	font-weight: 900;
	line-height: 1;
	position: relative;
	color: hsla(0, 0%, 0%, 0.6);
	transform-style: preserve-3d;
	perspective: 550px;
	z-index: 1;
}

Note that we have also added position:relative to the span because this will make the pseudo-elements’ absolute positioning work.

To clone the characters we use the content property to access the custom data-attribute. Then we’ll position both our pseudo-elements on top of their parent (the real letter).

.grid li span:before,
.grid li span:after {
	position: absolute;
	content: attr(data-letter);
	line-height: inherit;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 2;
	transition: all 0.3s;
}

.grid li span:before {
	text-shadow: none;
	color: hsla(0, 0%, 0%, 0.12);
}

In this way we’ll have the three layers: the first one is our main dark letter; the :before pseudo element will be our dark semi-transparent shadow on top of it, and the last layer is the :after pseudo element, the “peel” or opening piece on top of everything.

At this point it’s time to add our transformations. Let’s take a look at the letter that opens on the right side, i.e. where the peel is connected on the left: we’ll use transform-origin to ensure that the left side will become the hinge of the rotation:

.ot-letter-left span:before,
.ot-letter-left span:after {
	transform-origin: 0 50%;
}

Now we’ll add a little 3D rotation on the Y-axis of the :after element while we scale the shadow on the Y-axis and add a little vertical skew to it. A text-shadow will make the opening side more prominent, adding some thickness to the “peel” and hiding the hinge of the rotation.

.ot-letter-left span:before {
	transform: scale(1.08, 1) skew(0deg, 1deg);
}

.ot-letter-left span:after {
	text-shadow: 
		-1px 0px 0px hsla(360, 100%, 100%, 0.1), 
		3px 0px 1px hsla(0, 0%, 0%, 0.4);
	transform: rotateY(-15deg);
}

The real effect will now be applied on the :hover state of the list item: we’ll increase both the rotation and the skew of our pseudo-elements so that the letter will open and the shadow will change accordingly:

.ot-letter-left:hover span:before {
	transform: scale(0.85,1) skew(0deg,20deg);
}

.ot-letter-left:hover span:after {
	transform: rotateY(-40deg);
}

Let’s set some colors to finish off the effect (in our demo, each direction will have a different shade of red):

.ot-letter-left { 
	background: #e74d3c; 
}

.ot-letter-left span { 
	text-shadow: 
		1px 4px 6px #e74d3c, 
		0 0 0 hsla(0, 0%, 0%, 0.3), 
		1px 4px 6px #e74d3c; 
}

.ot-letter-left span:after { 
	color: #e74d3c; 
}

.ot-letter-left:hover span:after { 
	color: #ea6253; 
}

We set the background color of the grid item and then we’ll apply a little inset text-shadow effect to the cut-out part (the main span). That’s why we needed to set the text-shadow to .grid li span:before to none since it would be inherited otherwise. The :after pseudo-element, the top most peel piece, will get the same color as the background and on hover we’ll make it lighter since our imaginary light source is on the opposite side of the opening.

OpeningType_01

This is how our opening effect works. Beyond this, we can change the opening direction of the letters, playing with the transform-origin, the axis of rotation, the skew angle and some minor tweaks. The following style is an example of how our effect works in the bottom direction:

.ot-letter-bottom span:before,
.ot-letter-bottom span:after {
	transform-origin: 50% 0;
}

.ot-letter-bottom span:before {
	transform: scale(1,1.05) skew(4deg,0deg);
}

.ot-letter-bottom span:after {
	text-shadow: 
		0px -1px 0px hsla(360, 100%, 100%, 0.1), 
		0px 3px 1px hsla(0, 0%, 0%, 0.4);
	transform: rotateX(15deg);
}

.ot-letter-bottom:hover span:before {
	transform: translateY(-0.035em) scale(1,1.2) skew(10deg,0deg);
}

.ot-letter-bottom:hover span:after {
	transform: translateY(0.045em) rotateX(40deg);
}

As you can see, the transform-origin is always on the opposite side of the opening and the text-shadow is adjusted following the same logic.

Also, the axis of rotation is changed to the X-Axis and both, the scale and skew of the shadow pseudo-element are set to follow the direction of the light (as much as we can). As a final touch, we shifted both pseudo-elements using translateY to clear a little offset of the hinge.

That’s pretty much it, I hope you liked this tutorial and found it useful. Thank you for reading!

View demo Download source

Progress Button Styles

$
0
0

ProgressButtonStyles

View demo Download source

Today we’d like to share some progress button styles with you. You surely know “Ladda” by Hakim El Hattab, a UI concept that indicates progress directly on the button that invokes a loading action. Some of the buttons have a built-in progress bar and today we’d like to explore that idea with some creative progress button styles. Using perspective will allow us to create some fun 3D effects besides the flat “filling” styles. For a complete solution, please take a better look at Ladda.

Please note that we’ll be using transitions on pseudo-elements which are still not supported in some browsers (e.g. Safari and Mobile Safari).

Also note that we need transform-style: preserve-3d support for the 3D styles, which neither IE10 nor IE11 support.

With the script that we’ve created for showing the button styles, we take a simple button markup

<button class="progress-button" data-style="rotate-angle-bottom" data-perspective data-horizontal>Submit</button>

and transform it into the following structure:

<button class="progress-button" data-style="rotate-angle-bottom" data-perspective data-horizontal>
	<span class="progress-wrap">
		<span class="content">Submit</span>
		<span class="progress">
			<span class="progress-inner"></span>
		</span>
	</span>
</button>

If we don’t set the data-perspective attribute, then we’ll make this structure:

<button class="progress-button" data-style="fill" data-horizontal>
	<span class="content">Submit</span>
	<span class="progress">
		<span class="progress-inner"></span>
	</span>
</button>

We also indicate if we have a style that needs horizontal or vertical progress bar filling. This will be used in our CSS to specify the regarding styles.
The following styles are the general and common styles for all buttons (note that perspective styles are only needed for the buttons with 3D transforms):

*, *:after, *::before { box-sizing: border-box; }

@font-face {
	font-weight: normal;
	font-style: normal;
	font-family: 'icomoon';
	src:url('../fonts/icomoon/icomoon.eot');
	src:url('../fonts/icomoon/icomoon.eot?#iefix') format('embedded-opentype'),
		url('../fonts/icomoon/icomoon.ttf') format('truetype'),
		url('../fonts/icomoon/icomoon.woff') format('woff'),
		url('../fonts/icomoon/icomoon.svg#icomoon') format('svg');
}

.progress-button {
	position: relative;
	display: inline-block;
	padding: 0 60px;
	outline: none;
	border: none;
	background: #1d9650;
	color: #fff;
	text-transform: uppercase;
	letter-spacing: 1px;
	font-size: 1em;
	line-height: 4;
}

.progress-button[disabled],
.progress-button[disabled].state-loading {
	cursor: default;
}

.progress-button .content {
	position: relative;
	display: block;
}

.progress-button .content::before,
.progress-button .content::after  {
	position: absolute;
	right: 20px;
	color: #0e7138;
	font-family: "icomoon";
	opacity: 0;
	transition: opacity 0.3s 0.3s;
}

.progress-button .content::before {
	content: "\e600"; /* Checkmark for success */
}

.progress-button .content::after {
	content: "\e601"; /* Cross for error */
}

.progress-button.state-success .content::before,
.progress-button.state-error .content::after {
	opacity: 1;
}

.notransition {
	transition: none !important;
}

.progress-button .progress {
	background: #148544;
}

.progress-button .progress-inner {
	position: absolute;
	left: 0;
	background: #0e7138;
}

.progress-button[data-horizontal] .progress-inner {
	top: 0;
	width: 0;
	height: 100%;
	transition: width 0.3s, opacity 0.3s;
}

.progress-button[data-vertical] .progress-inner {
	bottom: 0;
	width: 100%;
	height: 0;
	transition: height 0.3s, opacity 0.3s;
}

/* Necessary styles for buttons with 3D transforms */

.progress-button[data-perspective] {
	position: relative;
	display: inline-block;
	padding: 0;
	background: transparent;
	perspective: 900px;
}

.progress-button[data-perspective] .content {
	padding: 0 60px;
	background: #1d9650;
}

.progress-button[data-perspective] .progress-wrap {
	display: block;
	transition: transform 0.2s;
	transform-style: preserve-3d;
}

.progress-button[data-perspective] .content,
.progress-button[data-perspective] .progress {
	outline: 1px solid rgba(0,0,0,0); /* Smoothen jagged edges in FF */
}

We are using the pseudo-elements ::before and ::after for the success or error icons which we fade in once loading is finished. The span with the class progress is used as the main wrapper for the progress bar itself which is the span with class progress-inner. Sometimes we use the progress span with a background color, while other times we will just style the child span. We’ll also provide some general styles for the vertical and horizontal case.

Note that for the 3D examples, we’ll use the button as a “shell” that will serve to add the perspective value. The content span will contain the button styles like the background color and the padding, and everything will be wrapped into a span with the class progress-wrap which will be the element that we transform.

An example of an individual button style is the following:

/* Rotate bottom 3d */
/* ====================== */

.progress-button[data-style="rotate-angle-bottom"] .progress {
	position: absolute;
	top: 100%;
	left: 0;
	width: 100%;
	height: 20px;
	box-shadow: 0 -1px 0 #148544; /* fix the blurriness that causes a gap */
	transform: rotateX(-90deg);
	transform-origin: 50% 0%;
}

.progress-button[data-style="rotate-angle-bottom"].state-loading .progress-wrap {
	transform: rotateX(45deg);
}

The button will have one of the three states (or none): state-loading, state-success and state-error.

For browsers that don’t support necessary properties, we’ll provide the default fallback of the first style (fill horizontal).

Icons are by IcoMoon and the icon font was created with the IcoMoon app.

We hope that you find these button styles inspiring and useful!

View demo Download source

Perspective Page View Navigation

$
0
0

PerspectiveNavigation

View demo Download source

Pushing the site content aside to reveal a navigation has certainly become a trend for mobile navigations. The approach reflects some practices in app design where “views” are shown with animations. We’ve experimented a bit and we’ve come up with a small set of effects that take the page and move it in 3D to reveal a navigation (or some other content if you like). What’s nice about this is that we literally put the site into perspective, allowing for an interesting view on the content and the navigation possibilities.

Please note that this is highly experimental, so let us know if you find any bugs or problems.

For the general effect to work, we need to wrap our page into a perspective wrapper. The main content container (that will get moved in 3D) and the navigation will be the two children immediate children of that wrapper:

<div id="perspective" class="perspective effect-airbnb">
	<div class="container">
		<div class="wrapper"><!-- wrapper needed for scroll -->
			<!-- ... -->
		</div><!-- wrapper -->
	</div><!-- /container -->
	<nav class="outer-nav left vertical">
		<!-- ... -->
	</nav>
</div><!-- /perspective -->

When we trigger the effect, we’ll need to change the position and overflow of the divisions to just show the current view. With a little trick we can hide the overflow but keep the scroll position by setting the “wrapper” top to the negative scrollTop value of the body.

Depending on which effect we have set as a class to the perspective wrapper, we’ll animate the container and the menu items once we click the trigger button. An example for an effect is the following, where we rotate and move the page to the left and make the navigation items appear consecutively with a slight delay on the right side:

/* Effect Move Left */
.effect-moveleft {
	background: #f4f3f1;
}

.effect-moveleft .container {
	transition: transform 0.4s;
	transform-origin: 50% 50%;
}

.effect-moveleft .container::after {
	background: rgba(255,255,255,0.6);
}

.effect-moveleft.animate .container {
	transform: translateX(-50%) rotateY(45deg) translateZ(-50px);
}

/* Fallback */
.no-csstransforms3d .effect-moveleft.animate .container {
	left: -75%;
}

/* Navigation */
.effect-moveleft .outer-nav a {
	color: #e86a32;
	opacity: 0;
	transform: translateX(100px) translateZ(-1000px);
	transition: transform 0.4s, opacity 0.4s;
}

.effect-moveleft .outer-nav a:hover {
	color: #333;
}

.effect-moveleft.animate .outer-nav a {
	opacity: 1;
	transform: translateX(0) translateZ(0);
}

.effect-moveleft.animate .outer-nav a:nth-child(2) {
	transition-delay: 0.04s;
}

.effect-moveleft.animate .outer-nav a:nth-child(3) {
	transition-delay: 0.08s;
}

.effect-moveleft.animate .outer-nav a:nth-child(4) {
	transition-delay: 0.12s;
}

.effect-moveleft.animate .outer-nav a:nth-child(5) {
	transition-delay: 0.16s;
}

.effect-moveleft.animate .outer-nav a:nth-child(6) {
	transition-delay: 0.2s;
}

.effect-moveleft.animate .outer-nav a:nth-child(7) {
	transition-delay: 0.24s;
}

We also added some example media queries that show how to resize or reposition the menu for smaller screens.

There are two styles for the menus which is a horizontal and a vertical one. Depending on where we push away the page, we’ll be using one of the orientations together with a position class:

<nav class="outer-nav left vertical">
	<a href="#" class="icon-home">Home</a>
	<a href="#" class="icon-news">News</a>
	<a href="#" class="icon-image">Images</a>
	<a href="#" class="icon-upload">Uploads</a>
	<a href="#" class="icon-star">Favorites</a>
	<a href="#" class="icon-mail">Messages</a>
	<a href="#" class="icon-lock">Security</a>
</nav>

The icons used in the demo are from the Typicons set by Stephen Hutchings and they are licensed under the CC BY-SA 3.0 license.

Here is how all the effects look like when the menu is visible and the page is pushed away:

Airbnb Effect:

PerspectivePageViewNavigation01

Move Left:

PerspectivePageViewNavigation02

Rotate Left:

PerspectivePageViewNavigation03

Move Down:

PerspectivePageViewNavigation04

Rotate Top:

PerspectivePageViewNavigation05

Lay down:

PerspectivePageViewNavigation06

We hope you like the effects and find them inspiring!

View demo Download source

“Look Inside” Book Preview with BookBlock

$
0
0

BookPreview

View demo Download source

There is something really fascinating about (real) books. Although we live in times where everything is digitalized by now, there is really nothing like picking up a real book and browsing through the pages. Many layouts on the web try to transmit that feeling by creating book-like experiences. On Codrops we’ve played many times with these kind of layouts, too. Today we’d like to show you a little concept for an online bookstore or book collection, using our BookBlock script. The idea is to show a grid of books where we can view some details of the book and where we can open the book to preview an excerpt. You surely know this kind of “look inside” option from Amazon, where you can have a taste of a book’s content. For the book preview we are using BookBlock in fullscreen and for the small books we use a structure with perspective that allows us to open the book in 3D.

Please note that this is just a proof-of-concept and might not work properly in older browsers.

For the book grid we use figures and this is how it looks:
BookPreview01

When we click on “view details”, we rotate the book in 3D and move it to the left side, allowing for the details to slide in from the right:
BookPreview02

Once “look inside” is clicked we perform a series of animations on the book, its cover and the BookBlock. The small book will open and scale up while the BookBlock fades in and scales up a bit. The fullscreen BookBlock shows the first preview pages:
BookPreview03

When clicking on one of the navigation arrows, we flip the respective page in 3D and reveal the next ones:
BookPreview04

Credits

We love playing with books in our experiments, so if you’d like to explore some similar articles and demos, check out these ones:

As mentioned before, this is an experimental concept implementation so if you find any bugs or glitches please let us know.

I hope you find this interesting and inspiring!

View demo Download source

Tilted Content Slideshow

$
0
0

TiltedContentSlideshow

View demo Download source

The FWA landing page has a really nice content slider that plays with 3D perspective on screenshots and animates them in an interesting way. Today we’d like to recreate part of that effect and make a simple content slideshow with some fancy 3D animations. The slideshow won’t be the same as the one on the FWA page: the items won’t be “floating” or moving on hover and we’ll only have a simple navigation.

If you have seen the effect over at the FWA landing page you will notice that the movement directions of the screenshots are random (moving up or down and sliding to the sides). We want to achieve the same effect by randomly adding some data-attributes that control the type of animation.

Please note that we’ll be using CSS 3D Transforms and CSS Animations which might not work in older or mobile browsers.

For the demo we are using some website screenshots from Zurb’s Responsive Gallery.

So, let’s get started!

The Markup

The slideshow has a main container with the class and ID “slideshow” and we can use an ordered list for our slides. Each list item contains a description with a title and a paragraph. It will also contain a division with the class “tiltview” where we will add our screenshots. The classes “col” an “row” will help us set the right layout for the inner anchors:

<div class="slideshow" id="slideshow">
	<ol class="slides">
		<li class="current">
			<div class="description">
				<h2>Some Title</h2>
				<p>Some description</p>
			</div>
			<div class="tiltview col">
				<a href="http://grovemade.com/"><img src="img/1_screen.jpg"/></a>
				<a href="https://tsovet.com/"><img src="img/2_screen.jpg"/></a>
			</div>
		</li>
		<li>
			<div class="description">
				<!-- ... -->
			</div>
			<div class="tiltview row">
				<!-- ... -->
			</div>
		</li>
		<li>
			<!-- ... -->
		</li>
	</ol>
</div>

We’ll also add a navigation element in our JavaScript which we’ll place right after the ordered list. It will consist of a nav with the right amount of spans.

Let’s already have a thought on how we will control the animations for each screenshot. In our script we set a data-attribute for a random incoming and outgoing animation. We’ll use the data-attributes data-effect-in and data-effect-out to control our animations in the CSS. We’ll check out the values for those attributes in a while. Let’s first check out the main style of the slideshow.

The CSS

Note that the CSS will not contain any vendor prefixes, but you will find them in the files (-webkit-).

Our slideshow wrapper and the ordered list will have the following style:

.slideshow {
	position: relative;
	margin-bottom: 100px;
}

.slides {
	list-style: none;
	padding: 0;
	margin: 0;
	position: relative;
	height: 500px;
	width: 100%;
	overflow: hidden;
	background: #ddd;
	color: #333;
}

The slideshow will be 500px high and we need to set the overflow to hidden, so that we don’t see the items fly out.
When we can’t build our slideshow because JavaScript is not enabled, we need to make sure that all slides are shown, so we set the height to auto:

.no-js .slides {
	height: auto;
}

Each list item will be positioned absolutely and occupy all available width and height. By default, we’ll set the visibility to hidden.
Each slide will also serve as the perspective container and we’ll define a perspective value of 1600px:

.slides > li {
	width: 100%;
	height: 100%;
	position: absolute;
	visibility: hidden;
	perspective: 1600px;
}

Let’s not forget the fallback:

.no-js .slides > li {
	position: relative;
	visibility: visible;
}

The navigation which is added dynamically, will appear as a set of lines. Each navigation item is a span and although we are using a tiny line, we want to make sure that the clickable area is actually bigger. This we can simulate by adding a white border:

.slideshow > nav {
	text-align: center;
	margin-top: 20px;
}

.slideshow > nav span {
	display: inline-block;
	width: 60px;
	height: 25px;
	border-top: 10px solid #fff;
	border-bottom: 10px solid #fff;
	background-color: #ddd;
	cursor: pointer;
	margin: 0 3px;
	transition: background-color 0.2s;
}

.slideshow > nav span:hover {
	background-color: #333;
}

.slideshow > nav span.current {
	background-color: #aaa;
}

The description will fill half of the width and since we want a transition on the opacity, we need to set it to 0 initially:

.description {
	width: 50%;
	padding: 2em 4em;
	font-size: 1.5em;
	position: relative;
	z-index: 1000;
	opacity: 0;
}

.no-js .description {
	opacity: 1;
}

.description h2 {
	font-size: 200%;
}

Now, let’s style the most crucial element in our slideshow. The division with the class “tiltview” will help us put our items into perspective. We need to add preserve-3d as transform style because some inner items will need to move on the Z-axis in some animations.
The “tiltview” wrapper will be centered by setting the top to 50% and transforming it -50% on the Y-axis. We’ll also rotate it on the X and Z-axis to create the 3D look:

.tiltview {
	position: absolute;
	left: 50%;
	width: 50%;
	top: 50%;
	transform-style: preserve-3d;
	transform: translateY(-50%) rotateX(60deg) rotateZ(35deg);
}

And the anchors and images will have the following style (the outline helps to avoid jagged edges in Firefox):

.tiltview a {
	outline: 1px solid transparent;
	backface-visibility: hidden;
}

.tiltview a,
.tiltview a img {
	max-width: 100%;
	display: block;
	margin: 0 auto;
}

.tiltview a:first-child {
	margin-bottom: 30px;
}

For the row and column cases we’ll set the widths accordingly:

.tiltview.row a {
	width: 48%;
	width: calc(50% - 15px);
	margin: 0;
}

.tiltview.row a:nth-child(2) {
	left: 50%;
	left: calc(50% + 15px);
	position: absolute;
	top: 0;
}

In our script we will use the classes “show” and “hide” to control the visibility of the slides:

/* Show/Hide */
.slides > li.current,
.slides > li.show {
	visibility: visible;
}

The description will fade in and out:

.description {
	transition: opacity 0.75s;
}

.current .description,
.show .description {
	opacity: 1;
}

.hide .description {
	opacity: 0;
}

As we mentioned before, we’ll control the animations by using some data-attributes. We have to define two types of animations: the incoming one (when we show the next slide) and the outgoing one (when we hide the previous slide).
We want to be able to animate the items in all possible directions, so we’ll need six different types: move up, move down, slide up, slide down, slide left, slide right. This makes a total of 12 animations (incoming and outgoing).

So, let’s define the first one for moving the outgoing element up:

/***********************/
/* Move up */
/***********************/

.hide[data-effect-out="moveUpOut"] .tiltview a {
	animation: moveUpOut 1.5s both;
}

.hide[data-effect-out="moveUpOut"] .tiltview a:nth-child(2) {
	animation-delay: 0.25s;
}

@keyframes moveUpOut {
	25% {
		animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
		transform: translateZ(-30px);
	}
	100% {
		transform: translateZ(3000px);
	}
}

We define a slight animation delay for the second item and we use a custom cubic-bezier timing function to add some interesting momentum.

The second animation for this movement is the incoming one which has the initial and end step reversed:

.show[data-effect-in="moveUpIn"] .tiltview a {
	animation: moveUpIn 1.5s 0.5s both;
}

.show[data-effect-in="moveUpIn"] .tiltview a:nth-child(2) {
	animation-delay: 0.75s;
}

@keyframes moveUpIn {
	0% {
		animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
		transform: translateZ(-3000px);
	}
	75% {
		transform: translateZ(30px);
	}
	100% {
		transform: translateZ(0);
	}
}

As you might have noticed, we could simplify the animation delay for the “hide” and the “show” case, but keeping the two rules separated will allow for easier adaption in case you’d like to define some different delays.

The resting animations are as follows:

/***********************/
/* Move down */
/***********************/
.hide[data-effect-out="moveDownOut"] .tiltview a {
	animation: moveDownOut 1.5s both;
}

.hide[data-effect-out="moveDownOut"] .tiltview a:nth-child(2) {
	animation-delay: 0.25s;
}

@keyframes moveDownOut {
	25% {
		animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
		transform: translateZ(30px);
	}
	100% {
		transform: translateZ(-3000px);
	}
}

.show[data-effect-in="moveDownIn"] .tiltview a {
	animation: moveDownIn 1.5s 0.5s both;
}

.show[data-effect-in="moveDownIn"] .tiltview a:nth-child(2) {
	animation-delay: 0.75s;
}

@keyframes moveDownIn {
	0% {
		animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
		transform: translateZ(3000px);
	}
	75% {
		transform: translateZ(-30px);
	}
	100% {
		transform: translateZ(0);
	}
}

/***********************/
/* Slide up */
/***********************/
.hide[data-effect-out="slideUpOut"] .tiltview a {
	animation: slideUpOut 1.5s both;
}

.hide[data-effect-out="slideUpOut"] .tiltview a:nth-child(2) {
	animation-delay: 0.25s;
}

@keyframes slideUpOut {
	25% {
		animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
		transform: translateY(30px);
	}
	100% {
		transform: translateY(-3000px);
	}
}

.show[data-effect-in="slideUpIn"] .tiltview a {
	animation: slideUpIn 1.5s 0.5s both;
}

.show[data-effect-in="slideUpIn"] .tiltview a:nth-child(2) {
	animation-delay: 0.75s;
}

@keyframes slideUpIn {
	0% {
		animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
		transform: translateY(3000px);
	}
	75% {
		transform: translateY(-30px);
	}
	100% {
		transform: translateY(0);
	}
}

/***********************/
/* Slide down */
/***********************/
.hide[data-effect-out="slideDownOut"] .tiltview a {
	animation: slideDownOut 1.5s both;
}

.hide[data-effect-out="slideDownOut"] .tiltview.row a:nth-child(2),
.hide[data-effect-out="slideDownOut"] .tiltview.col a:first-child {
	animation-delay: 0.25s;
}

@keyframes slideDownOut {
	25% {
		animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
		transform: translateY(-30px);
	}
	100% {
		transform: translateY(3000px);
	}
}

.show[data-effect-in="slideDownIn"] .tiltview a {
	animation: slideDownIn 1.5s 0.5s both;
}

.show[data-effect-in="slideDownIn"] .tiltview.row a:nth-child(2),
.show[data-effect-in="slideDownIn"] .tiltview.col a:first-child {
	animation-delay: 0.75s;
}

@keyframes slideDownIn {
	0% {
		animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
		transform: translateY(-3000px);
	}
	75% {
		transform: translateY(30px);
	}
	100% {
		transform: translateY(0);
	}
}

/***********************/
/* Slide left */
/***********************/
.hide[data-effect-out="slideLeftOut"] .tiltview a {
	animation: slideLeftOut 1.5s both;
}

.hide[data-effect-out="slideLeftOut"] .tiltview a:nth-child(2) {
	animation-delay: 0.25s;
}

@keyframes slideLeftOut {
	25% {
		animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
		transform: translateX(30px);
	}
	100% {
		transform: translateX(-5000px);
	}
}

.show[data-effect-in="slideLeftIn"] .tiltview a {
	animation: slideLeftIn 1.5s 0.5s both;
}

.show[data-effect-in="slideLeftIn"] .tiltview a:nth-child(2) {
	animation-delay: 0.75s;
}

@keyframes slideLeftIn {
	0% {
		animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
		transform: translateX(3000px);
	}
	75% {
		transform: translateX(-30px);
	}
	100% {
		transform: translateX(0);
	}
}

/***********************/
/* Slide right */
/***********************/
.hide[data-effect-out="slideRightOut"] .tiltview a {
	animation: slideRightOut 1.5s both;
}

.hide[data-effect-out="slideRightOut"] .tiltview.col a:nth-child(2),
.hide[data-effect-out="slideRightOut"] .tiltview.row a:first-child {
	animation-delay: 0.25s;
}

@keyframes slideRightOut {
	25% {
		animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
		transform: translateX(-30px);
	}
	100% {
		transform: translateX(3000px);
	}
}

.show[data-effect-in="slideRightIn"] .tiltview a {
	animation: slideRightIn 1.5s 0.5s both;
}

.show[data-effect-in="slideRightIn"] .tiltview.col a:nth-child(2),
.show[data-effect-in="slideRightIn"] .tiltview.row a:first-child {
	animation-delay: 0.75s;
}

@keyframes slideRightIn {
	0% {
		animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
		transform: translateX(-5000px);
	}
	75% {
		transform: translateX(30px);
	}
	100% {
		transform: translateX(0);
	}
}

Note that for some animations we need to define the animation delay for the first child instead of the second. We need to do this so that the anchors don’t overlap each other for some directions.

When we don’t have support for CSS 3D Transforms or transform-style: preserve-3d, then we want to provide a simple fallback:

/* Fallback for no 3D Transforms and no preserve-3d */
.no-csstransformspreserve3d .show .tiltview a,
.no-csstransformspreserve3d .hide .tiltview a,
.no-csstransforms3d .show .tiltview a,
.no-csstransforms3d .hide .tiltview a {
	animation: none !important;
}

.no-csstransforms3d .tiltview.col {
	top: -50%;
}

.no-csstransforms3d .tiltview.row {
	top: 20px;
}

And last, but not least, we need to make sure that we have a reasonable look for smaller screens. In this case we want the anchors with their screenshots to be just decoration, so we’ll set their opacity lower and make them be not clickable:

@media screen and (max-width: 65.3125em) {
	.description,
	.tiltview {
		width: 100%;
	}

	.tiltview {
		left: 0;
		opacity: 0.3;
		pointer-events: none;
	}
}

@media screen and (max-width: 33.75em) {
	.description {
		font-size: 1.1em;
	}

	.slideshow > nav span {
		width: 20px;
		height: 40px;
		margin: 0 10px;
	}
}

@media screen and (max-width: 24em) {
	.slides {
		height: 320px;
	}

	.description {
		font-size: 1em;
		padding: 1.4em;
	}

	.no-csstransforms3d .tiltview.col,
	.no-csstransforms3d .tiltview.row {
		top: 0;
	}
}

And that’s the style! Let’s do our slideshow script.

The JavaScript

We will start by initializing some variables, like the two arrays with the animation class names that control the incoming and outgoing of our items. These will be picked randomly and set to the items when we navigate the slideshow. Other variables are the items, the current value of the selected item (we assume this will be the first one) and the total number of items inside the slider:

function TiltSlider( el, options ) {
	this.el = el;
	// available effects for the animations (animation class names) - when an item comes in or goes out
	this.animEffectsOut = ['moveUpOut','moveDownOut','slideUpOut','slideDownOut','slideLeftOut','slideRightOut'];
	this.animEffectsIn = ['moveUpIn','moveDownIn','slideUpIn','slideDownIn','slideLeftIn','slideRightIn'];
	// the items
	this.items = this.el.querySelector( 'ol.slides' ).children;
	// total number of items
	this.itemsCount = this.items.length;
	if( !this.itemsCount ) return;
	// index of the current item
	this.current = 0;
	this.options = extend( {}, this.options );
	extend( this.options, options );
	this._init();
}

In order to navigate the slideshow we will add some navigation spans that, when clicked, will make the respective slideshow item appear. The total number of spans will be the same as the total number of items. Let’s add the navigation to our component:

TiltSlider.prototype._addNavigation = function() {
	// add nav "dots"
	this.nav = document.createElement( 'nav' )
	var inner = '';
	for( var i = 0; i < this.itemsCount; ++i ) {
		inner += i === 0 ? '' : '';
	}
	this.nav.innerHTML = inner;
	this.el.appendChild( this.nav );
	this.navDots = [].slice.call( this.nav.children );
}

Next, we need to bind the onclick event to the navigation spans. If we click on any other but the current span, then the current item should animate out and the new one should animate in.

TiltSlider.prototype._initEvents = function() {
	var self = this;
	// show a new item when clicking the navigation "dots"
	this.navDots.forEach( function( dot, idx ) {
		dot.addEventListener( 'click', function() {
			if( idx !== self.current ) {
				self._showItem( idx );
			}
		} );
	} );
}

We need to reference and work with the current item and also the next one that has to appear. We will add and remove classes from both of them in order to apply the respective animations. The animation (i.e. the data-attribute value) itself will be randomly picked from our animEffectsOut and animEffectsIn arrays as described before.

TiltSlider.prototype._showItem = function( pos ) {
	if( this.isAnimating ) {
		return false;
	}
	this.isAnimating = true;

	classie.removeClass( this.navDots[ this.current ], 'current' );

	var self = this,
		// the current item
		currentItem = this.items[ this.current ];

	this.current = pos;

	// next item to come in
	var nextItem = this.items[ this.current ],
		// set random effects for the items
		outEffect = this.animEffectsOut[ Math.floor( Math.random() * this.animEffectsOut.length ) ],
		inEffect = this.animEffectsIn[ Math.floor( Math.random() * this.animEffectsOut.length ) ];

	currentItem.setAttribute( 'data-effect-out', outEffect );
	nextItem.setAttribute( 'data-effect-in', inEffect );

	classie.addClass( this.navDots[ this.current ], 'current' );

	var cntAnims = 0,
		// the number of elements that actually animate inside the current item
		animElemsCurrentCount = currentItem.querySelector( '.tiltview' ).children.length, 
		// the number of elements that actually animate inside the next item
		animElemsNextCount = nextItem.querySelector( '.tiltview' ).children.length,
		// keep track of the number of animations that are terminated
		animEndCurrentCnt = 0, animEndNextCnt = 0,
		// check function for the end of each animation
		isFinished = function() {
			++cntAnims;
			if( cntAnims === 2 ) {
				self.isAnimating = false;
			}
		},
		// function for the end of the current item animation
		onEndAnimationCurrentItem = function() {
			++animEndCurrentCnt;
			var endFn = function() {
				classie.removeClass( currentItem, 'hide' );
				classie.removeClass( currentItem, 'current' );
				isFinished();
			};

			if( !isSupported ) {
				endFn();
			}
			else if( animEndCurrentCnt === animElemsCurrentCount ) {
				currentItem.removeEventListener( animEndEventName, onEndAnimationCurrentItem );
				endFn();
			}
		},
		// function for the end of the next item animation
		onEndAnimationNextItem = function() {
			++animEndNextCnt;
			var endFn = function() {
				classie.removeClass( nextItem, 'show' );
				classie.addClass( nextItem, 'current' );
				isFinished();
			};

			if( !isSupported ) {
				endFn();
			}
			else if( animEndNextCnt === animElemsNextCount ) {
				nextItem.removeEventListener( animEndEventName, onEndAnimationNextItem );
				endFn();
			}
		};

	if( isSupported ) {
		currentItem.addEventListener( animEndEventName, onEndAnimationCurrentItem );
		nextItem.addEventListener( animEndEventName, onEndAnimationNextItem );
	}
	else {
		onEndAnimationCurrentItem();
		onEndAnimationNextItem();
	}

	classie.addClass( currentItem, 'hide' );
	classie.addClass( nextItem, 'show' );
}

And that’s it! We hope you enjoyed this tutorial and find it useful!

Note that IE11 still does not support transform-style: preserve-3d, so the fallback will be shown there.

View demo Download source

3D Grid Effect

$
0
0

3dgrideffect

View demo Download source

Today we’d like to share a little animation concept with you. It’s the recreation of an effect we spotted in this fantastic prototype app by Marcus Eckert. The idea is to rotate a grid item in 3D, expand it into fullscreen and reveal some content. For our attempt to imitate the app behavior, we created two demos. In the first one we rotate the grid item vertically and in the second one horizontally.

Please note that this is just a proof-of-concept and that we are using several CSS properties that might not work in every browser (pointer-events, 3D Transforms, CSS Transitions). It is highly experimental and for browsers not supporting either one of those properties, we provide a simple fallback that just shows and hides the content.

The amazing illustrations featured in the demos are by Adam Quest. View all images from the Selected editorials 2014 Vol.1 on Behance and visit his Facebook page.

The way we simulate the effect seen in the prototype app video, is by creating a placeholder element that will have a front and a back face. The front will contain a copy of the grid item content and the back will be white. When clicking on a grid item, we add the absolutely positioned placeholder and position it in the clicked item’s position. Then we animate its width and height to the window’s width and height and set the top and left to negative values, making it move outside of the grid into the top left corner of the page. While we are doing that, we’ll also rotate the element in 3D, revealing the white back side of the placeholder. Once it fills the screen, we’ll fade in the content which we stored in a different division.

The illusion, that it’s actually the grid item that flies out and rotates, is completed by fading out the clicked grid item so that we can only see the placeholder being moved out of the grid.

In addition to the placeholder moving towards the viewer, we also move the grid away by translating it on the Z-axis.

Please note, that this is just a proof-of-concept. You might want to load your content dynamically (see the dummy loading effect) or show something else as the main content, i.e. a fullscreen image. The fallback is also very simple and general.

Let’s take a look at the markup and some important styles to understand the concept of how the effect is done.

We have a main section element which contains a division for the grid and one for the content:

<section class="grid3d vertical" id="grid3d">
	<div class="grid-wrap">
		<div class="grid">
			<figure><img src="img/1.jpg" alt="img01"/></figure>
			<figure><img src="img/2.jpg" alt="img02"/></figure>
			<figure><img src="img/3.jpg" alt="img03"/></figure>
			<!-- ... -->
		</div>
	</div><!-- /grid-wrap -->
	<div class="content">
		<div>
			<div class="dummy-img"></div>
			<p class="dummy-text">Some text</p>
			<p class="dummy-text">Some more text</p>
		</div>
		<div>
			<!-- ... -->
		</div>
		<!-- ... -->
		<span class="loading"></span>
		<span class="icon close-content"></span>
	</div>
</section>

When we click on a grid item, we’ll go by order to choose the matching content division. The content division also contains two spans, one for the activity indicator to simulate some loading, and one for the closing cross.

The placeholder for our rotation and expansion effect will be added dynamically to the grid and the structure is the following:

<div class="placeholder">
	<div class="front"><!-- content of clicked grid item --></div>
	<div class="back"></div>
</div>

Let’s have a look at some crucial styles.

The grid-wrap division will be the element with perspective:

.grid-wrap {
	margin: 10px auto 0;
	max-width: 1090px;
	width: 100%;
	padding: 0;
	perspective: 1500px;
}

In addition to the perspective value, we also set the perspective origin. But that we do dynamically depending on the view. If you, for example, view this grid on a smaller device where the grid height becomes very large, we don’t want the default perspective origin of 50% 50% because then an item that is far from the center of the whole grid will rotate away from the viewport (down or up). We’ll set the origin to be central to the viewer instead.

The grid will have a transition and we need to assign a preserve-3d transform-style to it because we want to be able to rotate its children in 3D:

.grid {
	position: relative;
	transition: all 0.5s cubic-bezier(0,0,0.25,1);
	transform-style: preserve-3d;
}

When we click on a grid item, we add the class view-full to the grid which will make the grid move away from us:

.view-full .grid {
	transform: translateZ(-1500px);
}

When we click on a grid item, we’ll make it fade out (our placeholder will be put in place):

.grid figure.active {
	opacity: 0;
}

The placeholder will have its pointer-events set to none and it will be positioned absolutely, unlike the other figures in the grid. It also needs the preserve-3d transform-style because we want to flip its backside:

.grid .placeholder {
	pointer-events: none;
	position: absolute;
	transform-style: preserve-3d;
	transition: all 0.5s ease-out;
}

The front and back side of the placeholder follow the classic 3D “card” style:

.placeholder > div {
	display: block;
	position: absolute;
	width: 100%;
	height: 100%;
	backface-visibility: hidden;
}

.placeholder .front img {
	width: 100%;
	height: 100%;
}

.placeholder .back {
	background: white;
	transform: rotateY(180deg);
}

The cloned image that we add to the front face of the placeholder is stretched to the full width and height to fill all the element.

Once we open a grid item we want the transition to have a bit of a delay and a custom timing-function:

.view-full .placeholder {
	transition: all 0.5s 0.1s cubic-bezier(0,0,0.25,1);
}

Depending on which kind of rotation we want, we set the according class to the main wrapper and set the following transform:

.vertical .view-full .placeholder {
	transform: translateZ(1500px) rotateX(-179.9deg);
}

.horizontal .view-full .placeholder {
	transform: translateZ(1500px) rotateY(-179.9deg);
}

This should of course be -180 degrees! But because browsers seem to have the liberty to choose which direction they rotate in this case, we need to set it to this awkward number (Firefox and Chrome choose opposing directions with -180 degrees).

The content division has fixed positioning and it will be fullscreen. We also want its inner content divisions to be scrollable, so we set the overflow-y to scroll and add -webkit-overflow-scrolling: touch for better mobile scrolling behavior:

.content {
	/* ... */
	overflow-y: scroll;
	height: 0;
	background: #fff;
	visibility: hidden;
	z-index: 400;
	-webkit-overflow-scrolling: touch;
}

When we want to open a specific content division, we first show the main content container:

.content.show {
	height: auto;
	pointer-events: auto;
	visibility: visible;
}

Each content division is placed absolutely and we set the initial opacity value to 0. We also need to set the height to 0 so that other invisible divisions don’t define the height of the whole thing.
To show a specific division, we need to set the following style:

.content > div.show {
	height: auto;
	opacity: 1;	
	transition: opacity 0.6s;
}

For the dummy content we define some transitions for the opacity and the transform. Depending on which rotation we choose, we set the initial translation of the dummy items to translate on the Y or the X-axis. Then, when we add the class “show” to their parent, we animate the translation to 0.

Take a look at the commented JavaScript to see how the functionality is implemented. As mentioned before, the fallback for browsers that don’t support some of the CSS properties in use, we provide a very basic fallback.

We hope you enjoy this little effect and find it inspiring!

View demo Download source

Draggable Dual-View Slideshow

$
0
0











DRaggableDualViewSlideshow

View demo Download source

Today we’d like to share an experimental slideshow with you. The idea is based on the great navigation concept from the Wild website where one can view the projects in either fullscreen or in a carousel mode. There are different techniques that would allow for such a layout; we tried to re-create this slideshow concept by using the Dragdealer.js library and 3D transforms. The main idea is to translate the slider on the Z axis, allowing it to be either fullscreen or of a smaller carousel size. By switching the actual size of the slideshow and removing the transforms when they are not needed anymore, we allow the slideshow to have a “real” size (i.e. 25% of the window). For the content part, we slide everything up and reveal a scrollable area.

Please note that this slideshow is highly experimental and only works properly in modern browsers.

The images used in the demo are from Unsplash.com.

When the slideshow is loaded, we show some info initially, that shows which interaction possibilities exist:
DraggableFullscreenSlideshow00

The main view of the slideshow is the fullscreen one. This is the only view shown for mobile:
DraggableFullscreenSlideshow01

When clicking on the arrow button, the content will be revealed in a sliding transition:
DraggableFullscreenSlideshow03

When clicking on the button for the view switch, the slideshow will be “zoomed out” to a smaller version:
DraggableFullscreenSlideshow02

Please note that at the time of release, Firefox (30.0, Mac & Windows) was the worst performing browser with issues around using 3D transforms, animations and transitions. Although we tried to fix all issues, some effects might not work properly.

We hope you enjoy this experiment and find it inspiring!

View demo Download source


Perspective Mockup Slideshow

$
0
0

MockupSlideshow

A while back, Franklin Ta wrote an article and made a really useful script for transforming an element in 3D in order to fit in a perspective mockup. In his article, he describes how the helper script can be used to create a 3D matrix transformation for embedding an iframe into a mockup image. We thought that it must be really interesting to add a slideshow in order to showcase ones work.

So we’ve used Franklin’s script to create the transformed elements and added a slideshow inside. In order to make the whole thing responsive (the transformation is based on pixels), we scale the main mockup in order to fit into its parent container. The nice thing of using the 3D matrix transforms is that we can use the “real” size for the images in the slideshow (i.e. based on the devices we display). Head over to Franklin’s article to learn how his script works in detail and in order to understand the interesting Math behind it.

In summary, the script can be executed using the console of your dev tools. The corners of the selected element can then be dragged into position and the transform value can be copied (if you inspect your element, you’ll see the value) and pasted into the respective class of the screen element.

Here is an example how we’ve added the transforms to one of our mockup screens (demo 1):

.mobile {
	overflow: hidden;
	position: absolute;
	z-index: 100;
	background: #333;
	width: 320px;
	height: 480px;
	top: 200px;
	left: 500px;
	outline: 1px solid transparent; /* For Firefox (jagged edges bug) */
	transform-origin: 0 0 0;
	transform: matrix3d(0.846234173238242, 0.251585817964749, 0, 0.000085171934399447, -0.115203182108559, 0.800700357116676, 0, -0.000214263459947427, 0, 0, 1, 0, 23, 14, 0, 1);
}

Don’t forget to add the -webkit- prefix for support in Safari, iOS Safari and Android browsers.

The simple slideshow plugin uses CSS animations to show and hide the slides. We’ve used some custom animations, but you can plug in any animation from Daniel Eden’s animate.css.

The styles for the slideshow are the following:

.slideshow {
	padding: 0;
	margin: 0;
	width: 100%;
	height: 100%;
	list-style-type: none;
}

.slideshow__item {
	width: 100%;
	height: 100%;
	position: absolute;
	overflow: hidden;
	pointer-events: none;
	z-index: 1;
	transform: translate3d(-100%, 0, 0);
}

.slideshow__item.current{
	pointer-events: auto;
	z-index: 100;
	transform: translate3d(0, 0, 0);
}

.slideshow img {
	width: 100%;
}

We “hide” the slides by translating them to the left (instead of using opacity, for example). The current item will get the class “current”.

An example for the animation classes is the following (demo 2):

.slideshow__item.in--next {
	animation: inNext 0.5s forwards;
}

.slideshow__item.out--next {
	animation: outNext 0.5s forwards;
}

.slideshow__item.in--prev {
	animation: inPrev 0.5s forwards;
}

.slideshow__item.out--prev {
	animation: outPrev 0.5s forwards;
}

@keyframes inPrev {
	0% {
		transform: translate3d(0, 100%, 0);
	}
	100% {
		transform: none;
	}
}

@keyframes inNext {
	0% {
		transform: scale3d(0.5, 0.5, 1);
	}
	100% {
		transform: none;
	}
}

@keyframes outPrev {
	100% {
		transform: scale3d(0.5, 0.5, 1);
	}
}

@keyframes outNext {
	100% {
		transform: translate3d(0, 100%, 0);
	}
}

Here you can check out some different examples:

MockupSlideshow01

MockupSlideshow02

MockupSlideshow03

MockupSlideshow04

In this last example we have two slideshows running at different times. This might be an interesting idea to showcase responsive works.

You can download the ZIP file of all demos here: Mockup Slideshow ZIP

We hope you like this little idea and find it useful!

A big thank you to the authors of the fantastic resources used in the demos:

Demo 2 image copyright by Vadim Sherbakov with granted permission to be used in our demo:

Perspective Mockup Slideshow was written by Mary Lou and published on Codrops.

Image Tilt Effect

$
0
0

ImageTiltEffect

View demo Download source

Today we’d like to share a little image effect with you. The idea is to add a tilt effect to an image by subtly moving copies of layers of semi-transparent divisions with the respective background-image. Maybe you’ve seen this effect already on sites like The DNA project by j.viewz, nclud or Daniel Spatzek’s Website. We’ve implemented this effect in one of our previous demos, the Photography Website Concept, and since we’ve gotten a couple of requests, we thought it would be interesting to create a little plugin so that it can be easily applied to any image.

Attention: This technique uses some CSS properties that only work in modern browsers (i.e. 3D Transforms). The effect only works on hover which means that the effect won’t be viewable on a touch device at this point.

ImageTiltEffect01

How it works

A normal image is replaced with layers of semi-transparent divisions of the same image. Every layer moves according to the configuration, creating a subtle motion effect. The initial image wrapper should have an explicit width and height set so that the divisions can be sized correctly. Have a look at the examples in the demo to see how it’s done.

ImageTiltEffect03

An image with the class “tilt-effect”

<div class="grid__img">
	<img class="tilt-effect" src="img/theimage.jpg" alt="The image" />
</div>

…gets transformed into a stack of divisions with the same background image:

<div class="grid__img">
    <div class="tilt">
        <div class="tilt__back" style="background-image: url(img/theimage.jpg);"></div>
        <div class="tilt__front" style="opacity: 0.7; -webkit-transform: perspective(1000px) translate3d(0px, 0px, 0px) rotate3d(1, 1, 1, 0deg); transform: perspective(1000px) translate3d(0px, 0px, 0px) rotate3d(1, 1, 1, 0deg); background-image: url(img/theimage.jpg);"></div>
        <div class="tilt__front" style="opacity: 0.7; -webkit-transform: perspective(1000px) translate3d(0px, 0px, 0px) rotate3d(1, 1, 1, 0deg); transform: perspective(1000px) translate3d(0px, 0px, 0px) rotate3d(1, 1, 1, 0deg); background-image: url(img/theimage.jpg);"></div>
    </div>
</div>

ImageTiltEffect02

Check out the demo for plugin options and examples. You’ll find some custom example styles in the demo.css.

We hope you enjoy this little plugin and find it useful!

View demo Download source

Image Tilt Effect was written by Mary Lou and published on Codrops.

Shaded Progress Bars: A CSS/Sass Exercise

$
0
0

CSSProgress

View demo Download source

Today we’d like to show you how to create some pure CSS progress bars with a special 3D look. Consider this tutorial an advanced CSS exercise that will give you insight in a lot of interesting 3D properties and shading techniques. Creating UI components using only CSS will train your ability to think outside of the box and in this tutorial we will show you some tricks on how to create a more complex shape, use it as a progress bar and animate it.

Attention: Note that some of the CSS properties are only supported in modern browsers. IE still does not support transform-style: preserve-3d, a crucial property for creating nested 3D structures; so the progress bars will be flat/not work in IE.
Browser Support:
  • ChromeSupported
  • FirefoxSupported
  • Internet ExplorerNot supported
  • SafariSupported
  • OperaSupported

We’ll make some use of Sass (together with Compass) in this tutorial, so make sure to get it set up and understand the basics:

If you’d like to use a full-fledged solution for animated progress bars, you should check out ProgressBar.js by Kimmo Brunfeldt or PACE by HubSpot for excellent page load progress bars.

For generating all the necessary prefixes you can use something like Autoprefixer or the plugin for Sublime Text.

We’ll use a lot of interesting CSS properties like transform, perspective and box-shadow. We’ll also make extensive use of SASS for saving plenty of time in generating the bars’ positions and skins. By using relative sizes (em, percentages), we’ll make sure that our progress bars are easily resizable.

Building the Faces

Let’s start by building a box which will contain all the six faces. This box will work as our main container setting the sizes of our bar and its view point. We’ll also use a wrapper for the perspective, and this wrapper’s font-size property will allow is to scale the progress bar with the help of some em unit magic.

To make sure that all the faces are part of our 3D space, we need to apply transform-style: preserve-3d to the box.

So let’s start writing our styles by initiating some color variables:

$light-gray: #e0e0e0;
$magenta: #ec0071;
$white: #f5f5f5;

.perspective {
	font-size: 5em; // sets the main scale size
	perspective: 12em; // sets the perspective
	perspective-origin: 50% 50%;
	text-align: center;
}

.bar {
	display: inline-block;
	width: 1em;
	height: 1em;
	margin-top: 1em;
	position: relative;
	transform: rotateX(60deg); // sets the view point
	transform-style: preserve-3d; // perspective for the children
}

Now, let’s think about the faces. If we want to be able to rescale our main box without problems, the faces contained inside must have a liquid behavior and an absolute position.

.bar {
	// -> The SCSS written before
	.bar-face {
		display: inline-block;
		width: 100%;
		height: 100%;
		position: absolute;
		bottom: 0;
		left: 0;
		background-color: rgba($light-gray, .6); // just to see what is happening
	}
}

Let’s write the markup and make sure it’s accessible:

<div class="perspective">
	<div class="bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
		<div class="bar-face"></div>
		<div class="bar-face"></div>
		<div class="bar-face"></div>
		<div class="bar-face"></div>
		<div class="bar-face"></div>
		<div class="bar-face"></div>
	</div>
</div>
If you are interested to learn more about accessibility, this article (written by Gez Lemon) has helped me a lot: ‘Introduction to WAI ARIA’

Setting Up the Faces

This is a very important part. Our bar’s faces must be well oriented, so that we don’t get into trouble when we start adding the percentage fills.

.bar {
	// -> The SCSS from before
	.bar-face {
		// -> The SCSS from before
		transform-origin: 50% 100%;
		&.roof {
			transform: translateZ(1em);
		}
		&.front {
			transform: rotateX(-90deg);
		}
		&.right {
			left: auto;
			right: -.5em;
			width: 1em;
			transform: rotateX(-90deg) rotateY(90deg) translateX(.5em);
		}
		&.back {
			transform: rotateX(-90deg) rotateY(0deg) translateZ(-1em);
		}
		&.left {
			width: 1em;
			transform: rotateX(-90deg)rotateY(-90deg) translateX(-.5em) translateZ(.5em);
		}
	}
}
<div class="perspective">
	<div class="bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
		<div class="bar-face roof"></div>
		<div class="bar-face front"></div>
		<div class="bar-face left"></div>
		<div class="bar-face right"></div>
		<div class="bar-face back"></div>
		<div class="bar-face floor"></div>
	</div>
</div>

pure-css-progress-1

Okay, this is a nice cube, but we want to build a rectangle for our bar. If you remember, we’ve already built the faces in a way to be liquid, so if we just increase the width of our .bar class we’ll get our shape. For this example we have used a width of 4em.

pure-css-progress-2

Building the Percentage Fills

The percentage fills will be contained inside our faces and, to keep our HTML code minimal, we’ll make use of the pseudo class :before. This generated :before element will grow to show the percentage relative to its face’s width.

.bar {
	// -> The SCSS from before
	.bar-face {
		// -> The SCSS from before
		&.percentage:before {
			content: '';
			display: block;
			position: absolute;
			bottom: 0;
			width: 0;
			height: 100%;
			margin: 0;
			background-color: rgba($magenta, .8);
			transition: width .6s ease-in-out;
		}
	}
}
<div class="perspective">
	<div class="bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
		<div class="bar-face roof percentage"></div>
		<div class="bar-face front percentage"></div>
		<div class="bar-face left"></div>
		<div class="bar-face right"></div>
		<div class="bar-face back percentage"></div>
		<div class="bar-face floor percentage"></div>
	</div>
</div>

pure-css-progress-2

Now we need to write the percentage fill style. It would be a tedious task to write one hundred classes by hand, so let’s write some sassy loop to get all the values for the aria-valuenow attribute from our HTML.

.bar {
	// -> The SCSS from before
	.bar-face {
		// -> The SCSS from before
	}

	@for $i from 0 to 101 {
		&[aria-valuenow='#{$i}'] {
			.percentage:before {
                width: $i * 1%;
			}
		}
	}
}

If you want to see it in action, just change the aria-valuenow attribute in the HTML from 0 to 100.

Building the Skin

For building our skins, we’ll use Sass mixins. In order to get a realistic look we’ll play with the box-shadow property. This property supports an array of values, and this array will let us emulate lightings. We’ll include the floor’s shadow and the face’s lighting in this property.

@mixin build-skin($color, $name) {
	&.#{$name} {
		.floor {
			box-shadow:
				0 -0.2em 1em rgba(0,0,0,.15),
				0 0.2em 0.1em -5px rgba(0,0,0,.3),
				0 -0.75em 1.75em rgba($white,.6);
		}
		.left {
			background-color: rgba($color, .5);
		}
		.percentage:before {
			background-color: rgba($color, .5);
			box-shadow: 0 1.6em 3em rgba($color,.25);
		}

	}
}
.bar {
	// -> The SCSS from before
	@include build-skin(#57caf4, 'cyan');
}
<div class="perspective">
	<div class="bar cyan" role="progressbar" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100">
		<div class="bar-face roof percentage"></div>
		<div class="bar-face front percentage"></div>
		<div class="bar-face left"></div>
		<div class="bar-face right"></div>
		<div class="bar-face back percentage"></div>
		<div class="bar-face floor percentage"></div>
	</div>
</div>

pure-css-progress-2

Also, we need a trick to illuminate our faces. If we type our face’s DOM nodes in the correct order we’ll see the magic happening:

<div class="perspective">
	<div class="bar cyan" role="progressbar" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100">
		<div class="bar-face roof percentage"></div>
		<div class="bar-face back percentage"></div>
		<div class="bar-face floor percentage"></div>
		<div class="bar-face left"></div>
		<div class="bar-face right"></div>
		<div class="bar-face front percentage"></div>
	</div>
</div>

pure-css-progress-2

What has happened here? It’s simple: while the browser is rendering an absolute element it adds an auto-incremented z-index by default (if we don’t edit this property). So, if we change the rendering order by putting the floor’s face first, its shadow will be over all the faces of the back side. That’s how we can apply a realistic shading.

And that’s all there is to this practical little progress bar! Now, make sure to check out all the demos and the files, and start building your own skins to train your skills.

Thank you for reading, we hope you enjoyed this tutorial and find it useful!

View demo Download source

Shaded Progress Bars: A CSS/Sass Exercise was written by Rafael González and published on Codrops.

Interactive Room Display

$
0
0

RoomDisplay800x600

View demo Download source

Today we’d like to share a little experiment based on a Dribbble shot by Bilal Mechairia’s, called “Spaces”. The idea is to show an interactive room with several items that all float in 3D space and move according to the position of the mouse. Once an item is clicked, more details pop up. Navigating between the room “slides” will rotate the different wall sections and add some interesting dynamic to the whole thing.

Attention: Some of the CSS properties, like 3D related ones, only work in modern browsers. It won’t work in IE where transform-style: preserve-3d is not supported.

Being a proof-of-concept, this implementation is highly experimental and there’s no fallback for browsers that don’t support preserve-3d.

RoomDisplay_01

Implementing such a 3D based component is quite tricky if one aims to go all the way and make everything “real 3D”. When we inspected the whole idea, it soon became clear that we can actually “fake” the perspective part of the room by cutting out the images and dividing them where we have a clean cut wall. Like that it was possible to rotate the pieces and make it look more 3D-like.

RoomDisplay_02

We basically did a slideshow where each slide is comprised of two or more sections that have the respective wall image. Then we added some items which are clickable and which expand with some more information. The slides are then animated by adding an animation class. This will trigger the slides to move and also the inner parts to do some rotation in 3D, creating a bit of depth. The whole scene rotates a bit as well when we move the mouse.

RoomDisplay_03

For the mobile, we’ve simply reduced the view to a listing of all items with the help of some media queries.

RoomDisplay_04

Browser Support:
  • ChromeSupported
  • FirefoxSupported
  • Internet ExplorerNot supported
  • SafariSupported
  • OperaSupported

We hope you enjoy this little experiment and find it useful!

Featured image mockup and iPhone mockup from PixelBuddha, MadeByVadim and designed by Vadim Scherbakov: iMac Mockup, iPhone Mockup.

View demo Download source

Interactive Room Display was written by Mary Lou and published on Codrops.

Cinema Seat Preview Experiment

$
0
0

CinemaSeatPreviewExperiment

View demo Download source

Maybe you are familiar with those ticket booking systems where, at some point during the purchase flow, you have to choose a seat. This is usually done when selling tickets for games, movies, flights or concerts. Wouldn’t it be cool to have some kind of “realistic” preview of the seat, i.e. see the stage or screen from the perspective of the space you chose? Of course it would :) This is the kind of question that resulted into a new experiment which we’d like to share with you today.

Attention: Some of the techniques we are using are very experimental and won’t work in all browsers. Support for transform-style: preserve-3d is necessary for this demo.

So the idea is to show some kind of cinema room where we can choose seats from a seating plan. When choosing a seat, we’ll move to the respective position in the room and allow the user to see the real view from the chosen place. There is also a button in the center of the page that allows to unlock the rotation of the viewer, something that is quite important for a realistic view considering that we can rotate and tilt our heads.

The trailer that we use in the demo is from Sintel, an animated movie by The Blender Foundation. It is licensed under Creative Commons Attribution 3.0.

Initially, we show a trailer box with the info of the movie and the option to choose the seats:

CinemaSeatPreviewExperiment_01

When we choose to select the seats, we’ll move the view to the back of the cinema room and show the seating plan:

CinemaSeatPreviewExperiment_02

Once a seat is clicked, the view moves to the respective position:

CinemaSeatPreviewExperiment_03

The little icon in the center of the screen allows for unlocking the view, i.e. allowing for the viewer to move around. This resembles the free movements of the head that are important for a realistic view.

At any point we can play the trailer and see how the screen is being perceived from that specific place.

Unfortunately, IE does not support transform-style: preserve-3d which breaks nested 3D elements. So this demo won’t work in the versions that don’t support it.

Browser Support:
  • ChromeSupported
  • FirefoxSupported
  • Internet ExplorerNot supported
  • SafariSupported
  • OperaSupported

We hope you enjoy this experiment and find it inspiring!

Check out the version by Sebastian Troć where the real seats are also colored: SebastianTroc/SeatPreview

View demo Download source

Cinema Seat Preview Experiment was written by Mary Lou and published on Codrops.

Viewing all 120 articles
Browse latest View live