Elastic SVG Elements

Some inspiration for elastic components with SVG shape animations for enhanced UI interactions.

Today we’d like to share some inspiration for adding elasticity to elements. The idea is to integrate an SVG element into a component and then animate it from one path to another with an elastic animation. Using SVGs like this can make things like menus, buttons or other elements more interesting and make the interaction look more organic with a natural feel to it. It’s of course important to keep things subtle and not exaggerate the bounciness. The nice thing is that we can give a more “realistic” interaction feedback to the user. Especially touch feedback can benefit from using this kind of effect. Based on this idea, we’ve created some inspirational examples of contexts where a morphing shape animation enhancement could make sense.

For animating the SVGs, we use Snap.svg, the excellent JavaScript SVG library for modern browsers.

The icons used in some of the demos are from the one and only Font Awesome icon set by Dave Gandy.

For the demo with the draggable & droppable elements we use Dragabilly by David DeSandro.

Please note that this is highly experimental and the demos were only tested in the latest versions of modern browsers.

An example of how we use the SVGs in the components (the sidebar menu in this case) is the following:

<nav id="menu" class="menu">
	<button class="menu__handle"><span>Menu</span></button>
	<div class="menu__inner">
		<ul>
			<li><a href="#"><i class="fa fa-fw fa-home"></i><span>Home<span></a></li>
			<li><a href="#"><i class="fa fa-fw fa-heart"></i><span>Favs<span></a></li>
			<li><a href="#"><i class="fa fa-fw fa-folder"></i><span>Files<span></a></li>
			<li><a href="#"><i class="fa fa-fw fa-tachometer"></i><span>Stats<span></a></li>
		</ul>
	</div>
	<div class="morph-shape" data-morph-open="M300-10c0,0,295,164,295,410c0,232-295,410-295,410" data-morph-close="M300-10C300-10,5,154,5,400c0,232,295,410,295,410">
		<svg width="100%" height="100%" viewBox="0 0 600 800" preserveAspectRatio="none">
			<path fill="none" d="M300-10c0,0,0,164,0,410c0,232,0,410,0,410"/>
		</svg>
	</div>
</nav>

The SVG is inserted after the inner menu and we use two data attributes to store the paths we will be animating the default path to (depending on whether we open or close the menu).

The SVG will be placed absolute into the menu, and enough spacing needs to be ensured on the sides so that we see the line moving elastically without getting cut off. Note that the SVGs are made responsive by using a width and height of 100% and not preserving the aspect ratio. This is important for some shapes as you might want to retain certain proportions and allow a stretching in one dimension only. For this example, although we always set the width and height to 100% in the HTML, we set a fixed width to the morph shape wrapper and the SVG:

.morph-shape {
	position: absolute;
	width: 240px;
	height: 100%;
	top: 0;
	right: 0;
}

.morph-shape svg path {
	stroke: #5f656f;
	stroke-width: 5px;
}

With Snap.svg we can then morph from one shape to another:

(function() {

	function SVGMenu( el, options ) {
		this.el = el;
		this.init();
	}

	SVGMenu.prototype.init = function() {
		this.trigger = this.el.querySelector( 'button.menu__handle' );
		this.shapeEl = this.el.querySelector( 'div.morph-shape' );

		var s = Snap( this.shapeEl.querySelector( 'svg' ) );
		this.pathEl = s.select( 'path' );
		this.paths = {
			reset : this.pathEl.attr( 'd' ),
			open : this.shapeEl.getAttribute( 'data-morph-open' ),
			close : this.shapeEl.getAttribute( 'data-morph-close' )
		};

		this.isOpen = false;

		this.initEvents();
	};

	SVGMenu.prototype.initEvents = function() {
		this.trigger.addEventListener( 'click', this.toggle.bind(this) );
	};

	SVGMenu.prototype.toggle = function() {
		var self = this;

		if( this.isOpen ) {
			classie.remove( self.el, 'menu--anim' );
			setTimeout( function() { classie.remove( self.el, 'menu--open' );	}, 250 );
		}
		else {
			classie.add( self.el, 'menu--anim' );
			setTimeout( function() { classie.add( self.el, 'menu--open' );	}, 250 );
		}
		this.pathEl.stop().animate( { 'path' : this.isOpen ? this.paths.close : this.paths.open }, 350, mina.easeout, function() {
			self.pathEl.stop().animate( { 'path' : self.paths.reset }, 800, mina.elastic );
		} );
		
		this.isOpen = !this.isOpen;
	};

	new SVGMenu( document.getElementById( 'menu' ) );

})();

With the right easing functions and appropriate timings, a slightly bouncy, organic movement can be created. But the options are so versatile and depend on the whole feel of a specific context, so the possibilities are endless 🙂

We hope you enjoy these little effects and find them inspiring!

Tagged with:

Manoela Ilic

Manoela is the main tinkerer at Codrops. With a background in coding and passion for all things design, she creates web experiments and keeps frontend professionals informed about the latest trends.

Stay up to date with the latest web design and development news and relevant updates from Codrops.

Feedback 38

Comments are closed.
  1. Wow, Great Elastic Effect. Esp i love that Dropdown and Bottom Menu Elastic thing. Planning to implement in my future projects. 🙂

  2. So cool !!

    I absolutely love the EXPAND

    One thing I noticed was on the INPUTS demo the effect only comes in when the user clicks into the field, not if they tab in. I’ve certainly found that one you click into the first form field one tends to just tab through, so it would be nice to add that in.

    I’m on Safari 8.0.

  3. Really amazing stuff, was wondering what the IE support is if anyone knows, I don’t have my VM’s setup is it IE9 or IE10+ ?

  4. Hi. I really love it. But I need put the ‘Sidebar Menu’ in the left side. Is complicated? What values I need modify? I greatly appreciate the any willing to help. Thanks!

  5. Incredible effects! Very timely inspiration for a school website I’m working on. I wonder though, how would I be able to try some of these examples while still giving the best possible experience to users with older browsers?

  6. great! together with semantic abilities, light weight we can construct fluid responsive interfaces. Awesome future!

  7. Yes, I freaking love how awesome this is. Just finished reading Five agency’s article on how they’re thinking about incorporating Google’s Material Design, so this was the perfect follow-up. Can’t wait to test this out. Thanks Mary Lou!

  8. Is there any legal problem or something if I use those designs in a official web page?
    Do I need to name this site or can I just use them without any problem?

  9. It looks awesome but it seems i dont have the brain to modiy any of it. Even simple things like changing icons to the ones i have.

    The other sidebar you made is amazing as well – Google nexus.

    Step 1 for me was to change icons in the drop down menu … failed 🙁
    Step 2 was to try and make an image appear next to the item in menu when hovering over that item .. failed again

    sigh

  10. Which parameter is responsible for the displacement of the cross and the line to the right?

    • Hi Douglas, you need to remove the following lines:
      // For Demo purposes only [].slice.call( this.el.querySelectorAll('a') ).forEach( function(el) { el.onclick = function() { return false; } } );

      Hope it helps! Cheers.

  11. Hi there , Can anyone please tell me how can i use just the sidebar effect in my site or in any site ? i have been trying for so long its been 3hours but i get able to use just the sidebar by selecting just the needed codes but im having a problem which is the close tag i mean ( the button to close the side bar cross logo) the background of it doesn’t get transparent i have tried a lot but as this thing is made with codes not an image that’s why maybe but guys please can anyone arrange it for me please or can i use a icon [png] here as a button svg animated icon?

  12. How did you come up with the initial paths? For example in the circular menu example, you have:

    data-morph-active=”M251,150c0,93.5-29.203,143-101,143S49,243.5,49,150C49,52.5,78.203,7,150,7S251,51.5,251,150z”

    d=”M281,150C281,221.797,221.797,281,150,281C78.203,281,19,221.797,19,150C19,78.203,78.203,19,150,19C221.797,19,281,78.203,281,150C281,150,281,150,281,150″

    • I’m wondering the same. Being able to control the elatic effects more precisely would be nice, but after fucking around with those path values I can’t figure out the formula for them.

  13. I am trying to use the pull up menu as a drop down menu on my site. It looks ok right now but because of how the original svg is created (and because I have no idea how to modify them) the height of the SVG is massive and covers up content as we start scrolling down. I’ve tried modifying the height but that actually makes the SVG smaller for some reason. I could really use some advice.

  14. Hi,

    How to combine circular menu and sidebar on the same page.
    I try it but there is a problem because of same classes names,
    Real mess, but great effect

    Thx

  15. Hi,

    i’m using a combination of Hamburger and dropdown – everything wirks fine, but the browser (FF, Chrome) does not open the link of the menu inside the dropdown.

    I went back a fe steps an could find the effect even in your Dropdown-Sample.
    All links ther are “#” but just try to link toa real site (e.g. http://www.google.com) -> the link is shown in status bar but does not open.

    Trying to play with pointer events on some levels of the stack didn’t worked.

    My Testsite with menu (top-right):
    http://wordpress.byinka.de

  16. Thanks for those ! 🙂

    For drop-down menu, what is the best pratice if we want to add several menus ? How do we get element ? by class ?

    Thanks

  17. Salut: Mary lou
    Merci de votre excelent travail.
    je suis entrain de creer mon site svt en HTML5 CSS3,priere de me donner aide pour appliquer quelques technique afin de donner une activite a mes sections surtout celles des exercices.
    je te demande le styles qui est appliquees dans les pages des exercices de ce site:
    musibiol.net/biologie/exercice/

  18. hi iam trying to use pull up men u but want to use it in reverse as it should be pull doen but not able to do it please help

  19. Nice tutorial.

    Is posible to do a drop-up menú based on drop-down menú.

    Thanks