Devil in the details: HOW TO BUILD A BULLETPROOF FULL-PAGE ROTATION ANIMATION THAT REVEALS A HIDDEN MENU WITH GREENSOCK (GSAP)

Devil is in the details

We’re going to build a simple-looking web page displaying one toggle button. When the toggle button is clicked, the page will rotate (-13°) degrees to reveal the navigation. Clicking the same button rotates the page (+13°) back into place.

We’ll use the GreenSock animation plugin to create performant UI animations based on the user’s interaction with the website.

The dynamic values that we will be working with are:

  • The current width of the user’s browser window.
  • The current vertical position of the page if the user has scrolled.

Click the Toggle button in the pen below to see the UI effect we are going to create.

See the Pen
DITD—Final Example
by Anthony Calzadilla (@clzd)
on CodePen.

Figure (1)

<div id="parent">
	<div id="child">
		<img src="thumbnail.png" alt="">
		<p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
		<img src="thumbnail.png" alt="">
		<p> ... </p>
	</div>
</div>

Create a #parent div. Make another #child div inside it with text, images and other content.

The following animated figures provide a conceptual overview of the UX animation. Each step is highlighted as an example with a corresponding text description. Explaining the logic, techniques and challenges involved for each example.

Figure (2)

Figured 02

  • Example (A)
    The #child will expand vertically to accommodate any text and/or content inside it. Likewise, #parent will expand to accommodate the height of #child.

Figure (3)

Figured 03

  • Example (B)
    We want to rotate #parent (-13°) degrees from the bottom-right corner of the content for the desired effect.
  • Example (C)
    But the longer the content is, the more horizontal distance is caused by the same rotational value of (-13°) degrees.

Figure (4)

Figured 04

THE FIX:
Remove #parent from the ‘flow’ of the document by switching its CSS to position:fixed. Then set its top, left, right and bottom properties to 0. Forcing its dimensions to be equal to the Window’s.

  • Example (D)
    Note: The longer the content is, the more distance caused by the rotational value of (-13°) degrees.
  • Example (E)
    Setting #parent‘s CSS to transform-origin:100% 100%. Makes the rotation point the bottom-right corner of the Window. Ensuring a consistent rotational distance regardless of content length.

THE VERTICAL POSITION GLITCH:
Because #parent was removed from the natural flow of the web page by setting CSS to position:fixed. #child loses its vertical position and defaults back to the top of the page. This is bad UX because user loses their place within the page they had scrolled to.

Figure (5)

Figured 05

ANOTHER FIX:
On click we get the pageOffsetY value of #child. Then use that value to move #child up when #parent ‘s CSS is set to position:fixed.

Figure (5) breaks down several steps that occur simultaneously. Although they appear as several linear examples for clarity. The following events happen all at once.

  • Example (F)
    Listening to the Window’s scroll-events and saving the value of distance scrolled in a variable.
  • Example (G)
    Note: Upon setting #parent to position: fixed, it loses its place in the flow of the document and #child ‘s vertical position resets to the top of the Window because it automatically defaults to its next closest ancestor element.
  • Example (H)
    Taking the previously saved pageYoffset value and using it as a negative translateY(-pageYoffset) property/value to move the content up by the distance scrolled. Preserving the user’s scroll position during the opening hinge animation.
  • Example (I)
    On close, we simultaneously remove the fixed positioning on #parent and the negative pageOffsetY of #child, rotate/animate the #parent back into its original position and set #parent back to position: static, remove the pageOffsetY value transformation value.

GSAP Code to Start Rotation Animation

Below is the code for the function that rotates the page when the user clicks toggle button. There are comments describing the important parts of the function. Please note that in the example below there are calls to other functions not illustrated in this post. Dive into the pen on CodePen for the full working code.

menuIn: () => {
    s.eBool = false;
    // Save the current scroll position to saveScroll
    s.saveScroll = s.last_known_scroll_position;
    // Create New GSAP Timeline
    var tl = new TimelineMax();
    tl.set(".nav_icon", { trasformOrigin: "50% 50%" }, "start")
    .set(".nav_icon path", { fill: "#666" }, "start")
    // Remove pointer events while page open animation is running
    .set([s.elBtn], { pointerEvents: "none", transformOrigin: "50% 50%" }, "start")
    .addLabel("go", "+=0.25")
    // Add 'go' class to <body>
    .call(MenuToggle.bodyClass, ["go"], this, "go")
    // Set <body> to overflow hidden
    .set(s.elBody, { overflow: "hidden" }, "go")
    // Move <#child>'s vertical position upwards using negative value of s.last_known_scroll_position
    .set(s.elChild, { y: -s.last_known_scroll_position }, "go")
    // Switch <#page> to position fixed and width/height 100% so it matches any Window 
    .set(s.elParent, { position: "fixed", overflow: "hidden", width: "100%", height: "100%" }, "go")
    // Rotate <#page> from the bottom-right corner of Window over 0.75 seconds
    .to(s.elParent, 0.75, { transformOrigin: "100% 100%", rotation: s.pageRotation, y: s.pageTop, ease: Back.easeOut.config(1.75) }, "open")
    // Scale toggle button 1.5x bigger over 0.25 seconds
    .to(s.elBtn, 0.25, { scale: 1.5, ease: Power2.easeIn }, "open")
    // Stagger in the social nav icons
    .staggerFrom(".nav_icon", 0.75, { y: "+=15px", scale: 0, autoAlpha: 0, rotation: -3, ease: Elastic.easeOut.config(1, 0.5) }, 0.15, "open")
    // Return pointer events to toggle button
    .set(s.elBtn, { pointerEvents: "all" });

    return tl;
}

GSAP Code to End Rotation Animation

Below is the code for the function that rotates the page back into its original position when the user clicks toggle button. There are comments describing the important parts of the function. Please note that in the example below there are calls to other functions not illustrated in this post. Dive into the pen on CodePen for the full working code.

 menuOut: () => {
    s.eBool = true;
    // Create New GSAP Timeline
    let tl = new TimelineMax();
    // Remove pointer events while page open animation is running
    tl.set(s.elBtn, { pointerEvents: "none" }, "abc")
    // Scale toggle button back to 1 over 0.1 seconds
    .to(s.elBtn, 0.1, { scale: 1, ease: Power2.easeIn }, "rotateOut")
    // Rotate <#page> back into original position over 0.45 seconds
    .to(s.elParent, 0.45, { rotation: 0, y: 0, ease: Back.easeIn.config(2) }, "rotateOut")
    // Fade and Scale social icons to 0 over 0.25 seconds
    .to(".nav_icon", 0.25, { scale: 0, autoAlpha: 0 }, "rotateOut")
    .to("html", 0.25, { backgroundColor: "#191718" }, "rotateOut+=0.28")
    // Switch <#page> to position relative and overflow to visible for scrolling 
    .set(s.elParent, { position: "relative", overflow: "visible", width: "100%", height: "100%" }, "out")
    // Clear inline style CSS of negative s.last_known_scroll_position added by GSAP
    .set(s.elChild, { clearProps: "all" }, "out")
    // Set  overflow to visible for scrolling
    .set(s.elBody, { overflow: "visible" }, "out")
    // Call unScroll() to reinstate users last scroll position before menu open
    .call(MenuToggle.unScroll)
    // Return pointer events to toggle button
    .set(s.elBtn, { pointerEvents: "all" })
    .set(".nav_icon", { clearProps: "all" });

    $('body').removeClass('go');
    return tl;
}               

Final Code

Below is the finished example. You can experiment directly with the code on Codepen.

See the Pen
DITD—Final Example
by Anthony Calzadilla (@clzd)
on CodePen.

Make Your Production CSS Ugly!

Paul Irish points out that production CSS should always be concatenated and as a result be super ugly to human eyes.

The file that you author should not be the one you deploy. The production CSS should be concatenated and run through a minifier and quite ugly to look at.

Meanwhile your original .sass or .css files are formatted however you like. Take pride in their layout, but be ruthless in making ugly files that go to production. 🙂

Direct link

How to Make a Responsive Logo Design

Mobile-First Responsive Websites provide users with the best possible experience afforded by their devices. Just as the UI and content will adapt to device widths and network capabilities. So should the website logo have adaptive qualities.

Simply reducing or enlarging a logo according to its context isn’t always the best solution. As the content area and device capabilities increase, designers are justified in adding additional details to the logo graphic itself.

I wanted to explore this idea and decided to create a little demo.

Explanation:

Using media queries and CSS3 properties we can add subtle shadows and effects to our logo as the screen size expands. This technique will work in most modern browsers. On older browsers it will simply fall back to the flat logo image. Which isn’t bad.

Side-by-side comparison of the logo before / after applying CSS3 effects.

I decided to use an inline SVG image for the logo because your logo is an image, not an h1. I used an SVG graphic because we need the logo to scale flawlessly.

This logo starts at a mobile-first size and scales up at 3 breakpoints. (The breakpoints are unimportant for our purposes and were chosen at random.) It will be small enough to fit on mobile devices. In this first version we have the logo mark and the logo text aligned on a single line. The logo text is the same size as the cross-section of the logo mark.

Break Point Break Down

BREAK POINT 1: On this one we keep the size of the logo text the same but we increase the size of the logo-mark so that now the logo-text aligns with the heart within the logo mark instead of the cross-section.

BREAK POINT 2: We add some shadow on the bottom of the logo. And a highlight at the top. We stack the logo text and increase the font-size of the top line so that it’s wider than the bottom line.

BREAK POINT 3: Finally we use CSS3 effects to create a faux 3D effect on the logo.*Note* Chunky 3d CSS3 text-effect originally by @mdo.

Take a look at the demo and move your browser window around.

CSS3 Animation & Wired Magazine – The Inside Story

Get the Insider Information on Css3 Animation

Did you know that Wired Magazine (iPad) might be the first publisher to use CSS3 animation as a major design element of a story? The cover story no less!

Ball-sy, eh?

How do I know this? I helped them do it!

The cover story of the June 2011 issue featured a bar graph representing the highest paying jobs in the USA. The idea was to have the text of the article floating over the bar graph. When a user swipes to a page the bar graph animates behind the floated text. (see video)

Working in the Dark

All the code was based on some pretty safe technical assumptions. Being that the screen size for iPads is around 768*1024, we have a good idea of where stuff should go. Because all the contents of the Wired magazine are downloaded prior to reading. We can rest assured that all the elements will be completely loaded and ready to animate the instant the user swipes onto the page. I didn’t have to worry about buggy animation.

There was no easy way of testing my work. The plan-of-attack was that I would write the html/css code in Textmate and they would build their layouts in InDesign. They would import my code and their Indesign layouts into the Adobe Digital Publishing Suite. From there they’d publish to the iPad in some magical way that… I can’t be quite bothered to fully understand yet.

Behind the Scenes of Mad Manimation

Click here to watch the CSS animation inspired by the Mad Men show opening credits. I’ve updated it with some simple GPU optimizations and auto-play once loaded. Compare the CSS animation to the original opening credits on YouTube.

You Call This Inspiration?

Imagine Don Draper walking into the office. His suitcase swings in his hand. His brand new Adidas squeak against the polished floor… Eh!? Adidas?

I love Adidas. This is the idea that popped into my head while watching the intro sequence to the Mad Men show. “Wouldn’t it be cool to re-create the Mad Men intro, but replace the man’s shiny shoes with a pair of classic Adidas?”

It was that ridiculous thought that gave me the idea for a CSS3 Mad Men intro. Dumb right? 🙂

I got to work.

Splitting the Scenes

The first task was to locate a high-quality version of the intro on youtube. After studying it closely I realized it could be duplicated easily using simple CSS3 animations.

Every time the camera angle changed, that would make a new scene. I paused the play head at the start and end of every scene and grabbed an image of both. This gave me “before and after” images for each scene. I would paste these on individual layers into a Photoshop file. Repeating the process until I had 16 .psd files (16 scenes) with a “before and after” layer in each one.

Duplicating the Graphics

I began drawing over the images I previously grabbed. Scenes 1 through 6 were pretty straight forward. I created shapes over the original images trying to duplicate the objects form, color and texture as closely as possible.

As I drew each graphic I had to be mindful of how I was going to animate them.

For instance, Scene 5, where the office collapses, has many moving pieces. By keeping Photoshop open on one screen and the mad men intro open on another. I was able to focus on a specific object and determine how many moving pieces each one needed.

Take the desk for example. If you look at the original intro closely you’ll see the desk falls apart into pieces as it slips down. By watching the desk pieces move I could determine which pieces obscured the others as they fell and I could start planning the html and stacking order of the graphics. It was a meticulous process and admittedly you have to be a bit nuts to undertake it. *Ahem*

Drawing the buildings that fly by as the silhouette falls wasn’t so fun. I ran into a little creative block with them. I wasn’t sure who or what I was going to place behind the glass. And I couldn’t figure out a good way to replicate that washed-out, hazy look the buildings have in the original.

Rather than get hung-up on the buildings. I figured I would draw basic shapes for them and match the perspective of the buildings. That way they would look as believable as possible when they where moving behind the falling silhouette. Later I could circle back to the buildings once I hammered out all the CSS3 animation.

I posted a little preview of the graphics to dribbble.

A Multinational Alliance

Enter Andy Clarke and Geri Coady. I worked with Andy and Geri previously on a CSS3 animation for his excellent book ‘Hardboiled Web Design by Andy Clarke‘. And I was stoked to be working with them again on this project.

The buildings I created sucked but ultimately served as a good foundation for Geri Coady’s artwork. She was able to create some incredible graphics of the ALA speakers. There is excellent design/photoshop work in those building panels. They merit close attention. Hopefully Geri will write a post on her site detailing how she created those amazing effects.

Hand Chiseled

The code for the animation is composed from an ordered list with 16 list-items. Within each list-item is all the html and images necessary for that particular scene. By default all these list-items are set to display: none.

We have a bit of jQuery that applies a “go” class to each list-item for a specific amount of time. This “go” class sets the list-item to display:block and activates the CSS3 animation assigned to that list-item (scene).

Once the specified amount of time has elapsed. The “go” class is removed from the list item. Setting it back to display: none, turning off the CSS3 animation and immediately applying the “go” class to the next list item in the order. Starting the whole chain of events again.

The code for the animation elements is ugly un-semantic html. But hey, sometimes you just have a good plan and say “fuck it”.

Hardboiled HTML

Andy had a plan for the ugly code. Browsers that didn’t support CSS3 animations will see an ordered list with an image and descriptions of each scene in the animation.

If the browser supports CSS3 animations we’ll use modernizr to replace each image and description with the html elements necessary for the animation. Simple!

Remember to click here to watch the CSS animation inspired by the Mad Men show opening credits. It has been updated with simple GPU optimizations and auto-play. Compare the CSS animation to the original opening credits on YouTube.

HTML5 section, aside, header, nav, footer elements: Not as obvious as they sound

This is a summary of Chapter 5 of Jeremy Kieth’s excellent book “HTML5 for Web Designers” by publisher A Book Apart. Bear in mind that this article is 1/4 my opinion and observations. The other 3/4 is para-phrasing directly out of the book.

Before we get to the section, aside, header, nav and footer elements it important we understand one of the foundational changes in html5. Each piece of sectioning content has its own self-contained outline. That means you don’t have to keep track of your heading level anymore-you can start from h1 each time. Because each piece generates its own outline, you can now get far more heading levels than simply h1 to h6. More importantly, you can start to think about your content in a truly modular way.

The fact that each piece of sectioning content has its own outline makes it perfect for Ajax. Porting a piece of content from one document to another introduces problems. CSS rules applied to the parent document will also apply to inserted content. HTML5 offers a solution with the ‘scoped’ attribute, which can be applied to a style element. Any styles declared within that style element will only be applied to the containing sectioning content.

Some of the new structural elements can be misleading. Especially the section, aside, header, nav and footer elements. Correct usage of the seemingly obvious elements can be confusing. Here’s a check list of common pitfalls to avoid:

  • section – Used for grouping together thematically-related content. Sounds like a div element, but its not. The div has no semantic meaning. Before replacing all your div’s with section elements, always ask yourself, “Is all of the content related?”
  • aside – Used for tangentially related content. Just because some content appears to the left or right of the main content isn’t enough reason to use the aside element. Ask yourself if the content within the aside can be removed without reducing the meaning of the main content. Pullquotes are an example of tangentially related content.
  • header – There is a crucial difference between the header element and the general accepted usage of header (or masthead). There’s usually only one header or ‘masthead’ in a page. In HTML5 you can have as many as you want. The spec defines it as “a group of introductory or navigational aids”. You can use a header in any section on your site. In fact, you probably should use a header within most of your sections. The spec describes the section element as “a thematic grouping of content, typically with a heading.
  • nav – Intended for major navigation information. A group of links grouped together isn’t enough reason to use the nav element. Site-wide navigation, on the other hand belongs in a nav element.
  • footer – Sounds like its a description of the position, but its not. Footer elements contain information about it’s containing element: who wrote it, copyright, links to related content, etc. Whereas we usually have one footer for an entire document, HTML5 allows us to also have footer within sections.

So you see? It’s not exactly as straight forward as it might seem. For a more indepth information about HTML5 please get “HTML5 for Web Designers” or check out the following free online resources: