Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                // images and data taken from https://randomuser.me
.container
	.body
		.status-bar Friends 
		.state.present.list
			.contact
				.display-pic
					img(src='https://randomuser.me/api/portraits/men/33.jpg', data-source=1).shared
				.name Brett Shelton 
			.contact
				.display-pic
					img(src='https://randomuser.me/api/portraits/women/6.jpg', data-source=2).shared
				.name Hailey Taylor 
			.contact
				.display-pic
					img(src='https://randomuser.me/api/portraits/men/47.jpg', data-source=3).shared
				.name Dennis Robinson
			.contact
				.display-pic
					img(src='https://randomuser.me/api/portraits/men/17.jpg', data-source=4).shared
				.name Bruce Davidson
			.contact
				.display-pic
					img(src='https://randomuser.me/api/portraits/men/20.jpg', data-source=5).shared
				.name Clarence Riley
			.contact
				.display-pic
					img(src='https://randomuser.me/api/portraits/men/55.jpg', data-source=6).shared
				.name Darryl Ramos
			.contact
				.display-pic
					img(src='https://randomuser.me/api/portraits/women/70.jpg', data-source=7).shared
				.name Avery Ramos
			.contact
				.display-pic
					img(src='https://randomuser.me/api/portraits/men/40.jpg', data-source=8).shared
				.name Alan Thompson
			.contact
				.display-pic
					img(src='https://randomuser.me/api/portraits/women/47.jpg', data-source=9).shared
				.name Wanda Adams
			.contact
				.display-pic
					img(src='https://randomuser.me/api/portraits/women/4.jpg', data-source=10).shared
				.name Jennie Thomas
		.state.next
			.details
				img(src='https://randomuser.me/api/portraits/men/33.jpg', data-dest=0).shared
				.name
              
            
!

CSS

              
                // colors
$white: #ffffff
$black: #000000
$light: #128c7e
$darkgrey: #777777
$yellow: #FEB942
$green: #075e54
$red: #E72159
$brand: #dcf8c6

*
	box-sizing: border-box

html, body
	width: 100%
	height: 100%
	background-color: $brand
	overflow: hidden
	font-family: 'Open Sans', Monospace, sans-serif
	
	.container
		background-color: $white
		height: 480px
		width: 320px
		position: absolute
		left: 50%
		top: 50%
		transform: translate(-50%, -50%)
		box-shadow: 5px 5px 10px 2px rgba($black, 0.5)
	
		.body
			height: 100%
			width: 100%
			position: relative
			display: flex
			flex-direction: column
	
			.status-bar
				width: 100%
				background-color: $green
				height: 50px
				color: $white
				font-weight: 700
				font-size: 20px
				display: flex
				align-items: center
				padding-left: 10px
				box-shadow: 0px 3px 10px 2px rgba($black, 0.5)
		
			.state
				height: 430px
				width: 100%
				top: 50px
				position: absolute
				display: block
				
				
				&.present
					visibility: visible
					opacity: 1
					transition-property: opacity, visibility
					transition-delay: 0.5s, 0.5s
				&.next
					visibility: hidden
					opacity: 0
					transition-property: opacity, visibility
					transition-delay: 0s, 0s
				
				&.list
					overflow-y: scroll
		
				&.list::-webkit-scrollbar-track
					box-shadow: inset 0 0 6px rgba($black, 0.3)
					border-radius: 10px
					background-color: rgba($brand, 0.3)
				&.list::-webkit-scrollbar
					width: 5px
					background-color: rgba($brand, 0.3)
				&.list::-webkit-scrollbar-thumb
					border-radius: 10px
					box-shadow: inset 0 0 6px rgba($black, 0.3)
					background-color: rgba($brand, 0.3)
		
				.contact
					width: 100%
					border-bottom: solid 1px rgba($black, 0.1)
					height: 60px
					display: flex
					cursor: pointer
		
					.display-pic
						flex-basis: 25%
						display: flex
						justify-content: center
						align-items: center
			
						img
							width: 50%
							height: auto
							border-radius: 50%
			
					.name
						flex-basis: 75%
						display: flex
						align-items: center
						justify-content: flex-start
						font-weight: 600
						color: $light
				
				.details
					width: 100%
					height: 100%
					display: flex
					flex-direction: column
					justify-content: space-around
					align-items: center
					
					img
						width: 200px
						height: auto
						border-radius: 0
			
					.name
						font-weight: 700
						color: $green
						font-size: 25px
						
              
            
!

JS

              
                const body = document.querySelector('body');
const contacts = Array.from(document.querySelectorAll('.contact'));
contacts.forEach(x => x.addEventListener('click', sharedImageTransition));
const pic = document.querySelector('.details');
pic.addEventListener('click', sharedImageTransition);

function sharedImageTransition() {
	const states = Array.from(document.querySelectorAll('.state'));
	// source coordinates
	const source = this.querySelector('.shared');
	const sourceCoords = source.getBoundingClientRect();
	const sourceRadius = getComputedStyle(source).borderRadius;
	
	// creating the dummy node
	const dummy = source.cloneNode();
	dummy.className = 'dummy';
	
	for (let attrb in sourceCoords) {
		dummy.style.setProperty(`${attrb}`, `${sourceCoords[attrb]}px`);
	}
	dummy.style.position = 'absolute';
	dummy.style.borderRadius = sourceRadius;
	dummy.style.transition = 'all 0.5s ease-out';
	body.appendChild(dummy);
	
	// destination coordinates
	let dest;
	if (source.dataset.dest) {
		dest = document.querySelector(`.next.state [data-source='${source.dataset.dest}']`);
	} else {
		dest = document.querySelector('.next.state .shared');
		dest.dataset.dest = source.dataset.source;
		const name = this.querySelector('.name').textContent;
		document.querySelector(`.next.state .name`).textContent = name;
		
	}
	const destCoords = dest.getBoundingClientRect();
	const destRadius = getComputedStyle(dest).borderRadius;
	
	// swap state
	states.forEach( x => {
		x.classList.toggle('next');
		x.classList.toggle('present');
	});
	
	// removing the dummy node after transition
	dummy.addEventListener('transitionend', function(e){
		dest.src = this.src;
		body.removeChild(this);	
	});

	// move
	for (let attrb in destCoords) {
		dummy.style.setProperty(`${attrb}`, `${destCoords[attrb]}px`);
	}
	dummy.style.borderRadius = destRadius;
}
              
            
!
999px

Console