JSFiddle - React, Tailwind, and code Playground
by phsiao2000
HTML
<script src="https://raw.github.com/LeaVerou/prefixfree/gh-pages/plugins/prefixfree.dynamic-dom.min.js"></script>
<main>
<h1>Flexible, fluid photoset</h1>
<p>The photoset is fluid: try resizing your browser. Dealing with margins and photos of different aspect ratios is also never a problem. <a href="https://medium.com/coding-design/7742e6f93d9e" title="Responsive Photosets">Read the tutorial on Medium</a>. Made by <a rel="author" href="http://terrymun.com" title="Visit me">Terry</a>.</p>
<p>A more advanced version of this technique, which dictates the size of the thumbnails depending on screen sizes, is <a href="http://codepen.io/terrymun/full/mvHky">available here</a>.</p>
<hr />
<div class="photoset">
<div class="photoset-row">
<figure class="photoset-item">
<a href="https://exposure-1.imgix.net/production/photos/j2kcj5iwwdtb6r5tnt9ni37ybwh3pplv34oq/original.jpg?1386624978&q=95&fm=jpg&w=617&h=206"><img src="https://exposure-1.imgix.net/production/photos/j2kcj5iwwdtb6r5tnt9ni37ybwh3pplv34oq/original.jpg?1386624978&q=95&fm=jpg&w=617&h=206" alt="ARoS Aarhus Kunstmuseum" title="ARoS Aarhus Kunstmuseum" /></a>
<figcaption>ARoS Aarhus Kunstmuseum. Photo © Terry Mun</figcaption>
</figure>
</div>
<div class="photoset-row">
<figure class="photoset-item">
<a href="http://500px.com/photo/4820790"><img src="https://exposure-2.imgix.net/production/photos/sw51tq1qtjrjo3xuazfjh2pby5tsz2tkeu74/original.jpg?1386624658&q=95&fm=jpg&w=411&h=274" alt="A lady walks briskly on a train platform in Bern, Switzerland." title="A lady walks briskly on a train platform in Bern, Switzerland." /></a>
<figcaption>A lady walks briskly on a train platform in Bern, Switzerland. Photo © Terry Mun</figcaption>
</figure>
<figure class="photoset-item">
<a href="http://500px.com/photo/20245695"><img src="http://i.imgur.com/BXo4qAz.jpg" alt="Inside Rundetårn, Copenhagen." title="Inside Rundetårn, Copenhagen." /></a>
<figcaption>Inside...
CSS
html {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 16px;
}
body {
color: #333;
line-height: 1.5em;
margin-bottom: 1.5em;
}
main {
margin: 0 auto;
padding: 1.5rem 0;
width: 80%;
}
h1 {
font-weight: bold;
font-size: 2em;
line-height: 1.5em;
text-align: center;
}
p {
margin-bottom: 1.5rem;
}
hr {
border: none;
border-top: .125rem solid #ddd;
margin-bottom: 1.375rem;
}
a {
border-bottom: 2px solid #333;
color: #333;
text-decoration: none;
transition: all .125s ease-in-out;
}
a:hover{
border-bottom-color: #4a7298;
color: #4a7298;
}
/* General photoset style */
.photoset {
overflow: hidden;
width: 100%;
}
.photoset .photoset-row {
margin-bottom: .5rem;
overflow: hidden;
width: 150%;
}
.photoset .photoset-row:last-child { margin: 0; }
.photoset .photoset-item {
display: block;
float: left;
margin: 0 .25rem;
}
.photoset .photoset-item:first-child { margin-left: 0; }
.photoset .photoset-item:last-child { margin-right: 0; }
.photoset figure {
margin: 0;
overflow: hidden;
position: relative;
}
.photoset figcaption {
background-color: rgba(255, 255, 255, .75);
box-sizing: border-box;
font-size: .75rem;
padding: .5rem;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
-webkit-transform: translateY(100%);
transform: translateY(100%);
transition: all .5s ease-in-out;
}
.photoset-item a {
border: 0;
display: block;
position: relative;
width: 100%;
height: 100%;
}
.photoset .photoset-item:hover a + figcaption {
-webkit-transform: translateY(0);
transform: translateY(0);
}
.photoset img {
display: block;
max-width: 100%;
transition: all .25s ease-in-out;
}
JavaScript
(function($,sr){
// debouncing function from John Hann
// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
var debounce = function (func, threshold, execAsap) {
var timeout;
return function debounced () {
var obj = this, args = arguments;
function delayed () {
if (!execAsap)
func.apply(obj, args);
timeout = null;
};
if (timeout)
clearTimeout(timeout);
else if (execAsap)
func.apply(obj, args);
timeout = setTimeout(delayed, threshold || 100);
};
}
// smartresize
jQuery.fn[sr] = function(fn){ return fn ? this.bind('resize', debounce(fn)) : this.trigger(sr); };
})(jQuery,'smartresize');
/* Wait for DOM to be ready */
$(function() {
// Detect resize event
$(window).smartresize(function () {
// Set photoset image size
$('.photoset-row').each(function () {
var $pi = $(this).find('.photoset-item'),
cWidth = $(this).parent('.photoset').width();
// Generate array containing all image aspect ratios
var ratios = $pi.map(function () {
return $(this).find('img').data('org-width') / $(this).find('img').data('org-height');
}).get();
// Get sum of widths
var sumRatios = 0, sumMargins = 0,
minRatio = Math.min.apply(Math, ratios);
for (var i = 0; i < $pi.length; i++) {
sumRatios += ratios[i]/minRatio;
};
$pi.each(function (){
sumMargins += parseInt($(this).css('margin-left')) + parseInt($(this).css('margin-right'));
});
// Calculate dimensions
$pi.each(function (i) {
var minWidth = (cWidth - sumMargins)/sumRatios;
$(this).find('img')
.height(Math.floor(minWidth/minRatio))
.width(Math.floor(minWidth/minRatio) * ratios[i]);
});
});
});
});
/* Wait for images to be loaded */
$(window).load(function () {
// Store original image dimensions
$('.photoset-item...