JSFiddle - React, Tailwind, and code Playground
by lollero
HTML
<script src="https://fonts.googleapis.com/css?family=Libre+Franklin:200,400,600,700|Nunito:300,400"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.min.js"></script>
<!-- Used libraries/services -->
<!-- http://lesscss.org/ -->
<!-- https://fonts.google.com/ -->
<!-- http://gsgd.co.uk/sandbox/jquery/easing/ -->
<!-- https://material.io/icons/ -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<img
class="caption"
data-overlay="#fff"
data-color="#E03DB4, #fff"
data-heading-one="Nam at accumsan urna"
data-heading-two="Curabitur pulvinar."
data-caption="Consectetur adipisicing elit. Autem, consequuntur 1."
src="http://joonas.me/1/dribbble-images/dribbble-1.png" alt=""
>
<img
class="caption"
data-color="#333, #fff"
data-heading-one="Maecenas faucibus convallis"
data-heading-two="Nam vitae."
data-caption="Aliquam volutpat odio vitae lectus feugiat venenatis. Curabitur id consectetur felis, ut ultricies orci. Nunc viverra quis nisl a consectetur. Ut pellentesque at ante ac porta. Mauris condimentum consequat congue. Phasellus sit amet tristique lacus. Donec commodo tristique sem."
src="http://joonas.me/1/dribbble-images/dribbble-2.png" alt=""
>
<img
class="caption"
data-overlay="true"
data-heading-one="Mauris vulputate dignissim odio"
data-heading-two="Pellentesque pharetra."
data-caption="Consectetur adipisicing elit. Autem, consequuntur 3."
src="http://joonas.me/1/dribbble-images/dribbble-3.png" alt=""
>
<img
class="caption"
data-heading-one="Sed pellentesque ligula"
data-heading-two="Cras nam dapibus feugiat."
data-caption="Aliquam posuere, ex sed fringilla fermentum, diam diam tempor enim, egestas laoreet nisl ante sit amet odio. Praesent urna enim, lobortis sed tristique quis, cursus non erat. In tempus, libero feugiat gravida rutrum, nunc mauris facilisis erat, eget blandit risus nulla at dolor. <br><br> Donec...
SCSS
.caption-wrapper {
position: relative;
float: left;
width: 430px; // With this we don't need to wait for the images to load before initiating the javascript.
height: 450px;
margin: 20px;
box-shadow: 0 1px 5px rgba(0,0,0, .1);
overflow: hidden;
background-clip: padding-box;
border-radius: 2px;
cursor: pointer;
img {
position: relative;
z-index: 0;
display: block;
}
.caption-overlay {
position: absolute;
z-index: 1;
top: 0px;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
background: #fff;
opacity: .65;
display: block;
}
.caption {
position: absolute;
z-index: 2;
left: 0;
right: 0;
bottom: 0px;
width: 100%;
background: #fff;
color: #000;
> div {
padding: 35px 25px;
}
.material-icons {
vertical-align: sub;
float: right;
opacity: .5;
}
&:hover .material-icons {
opacity: 1;
}
.caption-h1 {
font-family: 'Libre Franklin', sans-serif;
font-weight: 100;
font-size: 12px;
opacity: .5;
}
.caption-h2 {
font-family: 'Libre Franklin', sans-serif;
font-weight: 300;
font-size: 18px;
opacity: .95;
}
.caption-text {
width: 100%;
overflow: hidden;
font-family: 'nunito', sans-serif;
font-weight: 300;
font-size: 13px;
opacity: .6;
.divider {
margin-top: 20px;
height: 1px;
background: #f1f1f1;
margin-bottom: 20px;
}
}
}
}
JavaScript
var o, captionHeight,
caption = {
opt: {
caption: $('.caption'),
},
init: function() {
o = this.opt;
var $this = this;
o.caption.each(function() {
var _this = $(this),
_thisD = _this.data();
$this.constructHTML( _this, _thisD );
var wrapper = _this.parent();
$this.dimensions( wrapper );
$this.caption( _thisD, wrapper );
$this.overlay( _thisD, wrapper );
});
},
constructHTML: function( _this, _thisD ) {
_this.wrap('<div class="caption-wrapper"></div>');
_this.removeClass('caption');
var caption = $('<div class="caption"><div></div></div>').insertAfter( _this ).find('> div');
$('\
<div class="caption-heading">\
<div class="caption-h1">'+ _thisD.headingOne +'</div>\
<div class="caption-h2">\
<span>'+ _thisD.headingTwo +'</span>\
<i class="material-icons"></i>\
</div>\
</div>\
').appendTo( caption );
$('\
<div class="caption-text">\
<div class="divider"></div>\
<span>'+ _thisD.caption +'</span>\
</div>\
').appendTo( caption );
if ( _thisD.overlay ) {
$('<div class="caption-overlay"></div>').appendTo( _this.parent() );
}
},
dimensions: function( wrapper ) {
var captionT = wrapper.find('.caption-text');
captionT
.data({ captionHeight: captionT.height() })
.height(0);
},
caption: function( _thisD, wrapper ) {
var captionT = wrapper.find('.caption-text');
if ( _thisD.color ) {
var color = _thisD.color.split(', ');
wrapper.find('.caption').css({
background: color[0],
color: color[1]
});
}
wrapper.on("mouseenter mouseleave", function( e ) {
if ( e.type === "mouseenter" ) {
captionT.stop().animate({
height: captionT.data().captionHeight
}, 180, "easeOutBack");
}
else {
captionT.stop().animate({
height: 0
}, 300, "easeOutBack");
}
});
},
overlay: function( _thisD, wrapper ) {
var overlay = wrapper.find('.caption-overlay');
if (...