<div class="title">
<h2>Sortable Vertical Timeline</h2>
<h4><b>How use</b>: Drag and drop any object in timeline and feel the experience :)</h4>
</div>
<div class="Timeline" id="Timeline">
<div class="Timeline-line">
<div class="Timeline-line-menu"></div>
</div>
<div class="Timeline-item">
<div class="Timeline-item-inner">
<div class="Timeline-item-index"></div>
<div class="Timeline-item-top">
<div class="Timeline-item-top-type">
<i></i> <span>Item</span>
</div>
</div>
<div class="Timeline-item-content">
<div class="Timeline-item-content-title">
Lorem ipsum dolor sit amet, consectetur adipisicing.
</div>
<div class="Timeline-item-content-body"></div>
</div>
</div>
</div>
<div class="Timeline-item Timeline-item--quote">
<div class="Timeline-item-inner">
<div class="Timeline-item-index"></div>
<div class="Timeline-item-top">
<div class="Timeline-item-top-type">
<i></i> <span>Quote</span>
</div>
</div>
<div class="Timeline-item-content">
<div class="Timeline-item-content-title">
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p>
</blockquote>
</div>
<div class="Timeline-item-content-body"></div>
</div>
</div>
</div>
<div class="Timeline-item Timeline-item--image">
<div class="Timeline-item-inner">
<div class="Timeline-item-index"></div>
<div class="Timeline-item-top">
<div class="Timeline-item-top-type">
<i></i> <span>Image</span>
</div>
</div>
<div class="Timeline-item-content">
<div class="Timeline-item-content-title">
Lorem ipsum dolor sit amet, consectetur adipisicing.
</div>
<div class="Timeline-item-content-body">
<img src="http://fakeimg.pl/350x200/ddd/FFF/?text=Hola">
</div>
</div>
</div>
</div>
<div class="Timeline-item">
<div class="Timeline-item-inner">
<div class="Timeline-item-index"></div>
<div class="Timeline-item-top">
<div class="Timeline-item-top-type">
<i></i> <span>Video</span>
</div>
</div>
<div class="Timeline-item-content">
<div class="Timeline-item-content-body">
<iframe src="//player.vimeo.com/video/112719694?title=0&byline=0&portrait=0" width="100%" height="281" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
</div>
</div>
</div>
<div class="Timeline-item">
<div class="Timeline-item-inner">
<div class="Timeline-item-index"></div>
<div class="Timeline-item-top">
<div class="Timeline-item-top-type">
<i></i> <span>Item</span>
</div>
</div>
<div class="Timeline-item-content">
<div class="Timeline-item-content-title">
Lorem ipsum dolor sit amet, consectetur adipisicing.
</div>
<div class="Timeline-item-content-body"></div>
</div>
</div>
</div>
<div class="Timeline-item Timeline-item--quote">
<div class="Timeline-item-inner">
<div class="Timeline-item-index"></div>
<div class="Timeline-item-top">
<div class="Timeline-item-top-type">
<i></i> <span>Quote</span>
</div>
</div>
<div class="Timeline-item-content">
<div class="Timeline-item-content-title">
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolorum inventore quas deserunt, reprehenderit est doloribus praesentium minima sequi repudiandae libero!</p>
</blockquote>
</div>
<div class="Timeline-item-content-body"></div>
</div>
</div>
</div>
<div class="Timeline-item">
<div class="Timeline-item-inner">
<div class="Timeline-item-index"></div>
<div class="Timeline-item-top">
<div class="Timeline-item-top-type">
<i></i> <span>Item</span>
</div>
</div>
<div class="Timeline-item-content">
<div class="Timeline-item-content-title">
Lorem ipsum dolor sit amet, consectetur adipisicing.
</div>
<div class="Timeline-item-content-body"></div>
</div>
</div>
</div>
<div class="Timeline-item">
<div class="Timeline-item-inner">
<div class="Timeline-item-index"></div>
<div class="Timeline-item-top">
<div class="Timeline-item-top-type">
<i></i> <span>Item</span>
</div>
</div>
<div class="Timeline-item-content">
<div class="Timeline-item-content-title">
Lorem ipsum dolor sit amet, consectetur adipisicing.
</div>
<div class="Timeline-item-content-body"></div>
</div>
</div>
</div>
<div class="Timeline-item Timeline-item--image">
<div class="Timeline-item-inner">
<div class="Timeline-item-index"></div>
<div class="Timeline-item-top">
<div class="Timeline-item-top-type">
<i></i> <span>Image</span>
</div>
</div>
<div class="Timeline-item-content">
<div class="Timeline-item-content-title">
Lorem ipsum dolor sit amet, consectetur adipisicing.
</div>
<div class="Timeline-item-content-body">
<img src="http://fakeimg.pl/350x100/ddd/FFF/?text=Chao">
</div>
</div>
</div>
</div>
<div class="Timeline-item Timeline-item--image">
<div class="Timeline-item-inner">
<div class="Timeline-item-index"></div>
<div class="Timeline-item-top">
<div class="Timeline-item-top-type">
<i></i> <span>Image</span>
</div>
</div>
<div class="Timeline-item-content">
<div class="Timeline-item-content-title">
Lorem ipsum dolor sit amet, consectetur adipisicing.
</div>
<div class="Timeline-item-content-body">
<img src="http://placekitten.com/350/208">
</div>
</div>
</div>
</div>
</div>
@import "bourbon";
/*--------------------------------------------
Name: Timeline
Created: 13/02/15
Author: Raúl Hernández <[email protected]>
Github: raulghm
----------------------------------------------*/
/*
Using BEM SuitCSS variant, see: https://github.com/suitcss/suit/blob/master/doc/naming-conventions.md
*/
$brand-primary: #999;
$gray-darker: lighten(#000, 46.5%); // #777
$gray-dark: lighten(#000, 60.5%); // #999
$gray: lighten(#000, 79%); // #c9c9c9
$gray-light: lighten(#000, 87%); // #dedede
$gray-lighter: lighten(#000, 92%); // #ebebeb
$font-family-sans-serif: Helvetica, Arial, sans-serif;
$font-family-serif: Georgia, "Times New Roman", Times, serif;
// font-size helper
@mixin font-size($size) {
// html font-size is 62.5% (base 10)
font-size: ($size * 10) + px; // fallback in px
font-size: $size + rem;
}
.cf:before,
.cf:after {
content: " "; /* 1 */
display: table; /* 2 */
}
.cf:after {
clear: both;
}
/**
* For IE 6/7 only
* Include this rule to trigger hasLayout and contain floats.
*/
.cf {
*zoom: 1;
}
body {
padding: 40px;
}
.title {
text-align: center;
margin-bottom: 60px;
color: #777;
h2, h4 {
font-family: $font-family-serif;
}
}
$component: 'Timeline';
.#{$component} {
width: 830px;
margin: 0 auto;
position: relative;
&-line {
width: 40px;
height: 100%;
position: absolute;
left: 50%;
margin-left: -20px;
padding-left: 20px;
cursor: pointer;
&:after {
content: "";
position: absolute;
border-left: 1px solid $gray-light;
height: 100%;
}
&.is-active {
.#{$component} {
&-line {
&-menu {
opacity: 1;
}
}
}
}
}
&.is-dragging {
.#{$component} {
&-item {
&-inner {
margin: 0;
opacity: .7;
}
}
}
}
&-item {
width: 100%;
position: relative;
@extend .cf;
z-index: 90;
&-inner {
position: relative;
margin-bottom: 40px;
width: 345px;
border: 1px solid $gray-light;
transition: all .3s ease;
margin: -10px 0 -20px;
&:before {
content: "";
position: absolute;
top: 50%;
right: -78px;
border-radius: 50%;
transform: translateY(-50%);
background-color: $brand-primary;
width: 12px;
height: 12px;
}
// triangle right
&:after {
content: "";
width: 20px;
height: 20px;
position: absolute;
right: -9px;
top: 50%;
@include triangle(16px, $gray-light, right);
transform: translateY(-50%);
transition: all .2s ease;
}
}
&:hover {
user-select: none;
-webkit-user-select: none;
&:after {
border-left-color: $brand-primary;
}
.#{$component} {
&-item {
&-inner {
border-color: $brand-primary;
&:after {
@include triangle(16px, $brand-primary, right);
}
}
&-top {
&-tools {
opacity: 1;
}
}
}
}
}
&:nth-child(odd) {
margin-left: 50%;
padding-left: 70px;
width: 50%;
&:hover {
.#{$component} {
&-item {
&-inner {
&:after {
@include triangle(16px, $brand-primary, left);
}
}
}
}
}
.#{$component} {
&-item {
&-inner {
&:before {
right: auto;
left: -77px;
}
&:after {
@include triangle(16px, $gray, left);
border-left: 0;
right: auto;
left: -9px;
}
}
&-index {
opacity: .6;
left: -45px;
right: auto;
}
}
}
}
&.is-dropping {
cursor: -webkit-grabbing;
}
&-index {
position: absolute;
right: -45px;
top: 50%;
transform: translateY(-50%);
color: $gray;
@include font-size(2.4);
font-weight: 200;
font-family: $font-family-serif;
}
&--quote {
.#{$component} {
&-item {
&-content {
font-family: $font-family-serif;
}
}
}
}
&--image {
.#{$component} {
&-item {
&-content {
&-body {
img {
max-width: 100%;
margin-top: 5px;
}
}
}
}
}
}
&-top {
background-color: #f8f8f8;
padding: 10px 15px;
@extend .cf;
&:hover {
cursor: move;
cursor: -webkit-grab;
}
&-type {
float: left;
text-transform: uppercase;
letter-spacing: 1px;
@include font-size(1.1);
i {
@include font-size(1.6);
}
span {
margin-left: 10px;
}
}
}
&-content {
background-color: #fff;
padding: 10px 20px 20px;
text-align: left;
&-title {
@include font-size(1.8);
}
&-image {
background-size: cover;
background-position: 50%;
background-repeat: no-repeat;
height: 135px;
width: 341px;
margin-top: 10px;
margin-left: -20px;
}
&-body {
position: relative;
&:empty {
display: none;
}
}
}
}
}
View Compiled
/* Sortable — is a minimalist JavaScript library for reorderable drag-and-drop lists on modern browsers and touch devices. No jQuery. Supports Meteor, AngularJS, React and any CSS library, e.g. Bootstrap.
https://github.com/RubaXa/Sortable */
var $component = 'Timeline';
function sort() {
var $itemIndex = 0;
console.log('reorder');
$('.' + $component).find('.' + $component + '-item').each(function(index) {
index++;
$itemIndex = (index < 10) ? '0' + index : index;
$(this).find('.' + $component + '-item-index').text($itemIndex);
if (index % 2 === 0) {
$(this).addClass('is-right');
}
else {
$(this).removeClass('is-right');
}
});
}
$(document).ready(function(){
sort();
var el = document.getElementById($component);
var sortable = Sortable.create(el, {
draggable: '.' + $component + "-item",
handle: '.' + $component + "-item-top",
animation: 250,
scroll: true, // or HTMLElement
scrollSensitivity: 60, // px, how near the mouse must be to an edge to start scrolling.
scrollSpeed: 10, // px
ghostClass: "is-dropping",
onStart: function (event) {
$('.' + $component).toggleClass('is-dragging');
console.log('onStart')
},
onEnd: function (event) {
$('.' + $component).toggleClass('is-dragging');
sort();
},
});
});