Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

JavaScript

Babel is required to process package imports. If you need a different preprocessor remove all packages first.

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

Behavior

Save Automatically?

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

              
                <div class="card">

   <h2>Men's Harem Pants</h2>

   <div id="photo-viewer"></div>

   <div class="info">
      <p>Men's elephant pattern harem pants in black. Elastic band waist.</p>
      <p><strong>Measurements:</strong></p>
      <ul>
         <li>Waist: 34" - 48"</li>
         <li>Length: 44"</li>
      </ul>
   </div>

   <div class="actions">
      <a class="thumb" href="https://harempants.imgix.net/s/files/1/0754/0497/products/0018_SURE_DESIGN_278_of_410.jpg" >
         <img src="https://harempants.imgix.net/s/files/1/0754/0497/products/0018_SURE_DESIGN_278_of_410.jpg" />
      </a>
      <a class="thumb" href="https://harempants.imgix.net/s/files/1/0754/0497/products/M-HPAP25-Black-10.jpg">
         <img src="https://harempants.imgix.net/s/files/1/0754/0497/products/M-HPAP25-Black-10.jpg" />
      </a>
      <a class="thumb" href="https://harempants.imgix.net/s/files/1/0754/0497/products/0015_SURE_DESIGN_282_of_410.jpg">
         <img src="https://harempants.imgix.net/s/files/1/0754/0497/products/0015_SURE_DESIGN_282_of_410.jpg" />
      </a>
      <button>Buy now</button>
   </div>

</div>
              
            
!

CSS

              
                /* -------- LAYOUT ----------*/

* {
   box-sizing: border-box;
}

.card {
   display: block;
   width: 600px;
   margin: 80px auto;
}

h2 {
   margin-bottom: 20px;
}

div#photo-viewer {
   height: 300px;
   width: 300px;
   overflow: hidden;
   display: inline-block;
   position: relative;
}

div.info {
   width: 220px;
   height: 300px;
   display: inline-block;
   vertical-align: top;
   margin-left: 20px;
}

.thumb {
   margin-right: 8px;
}

.thumb img {
   height: 70px;
}

.actions button {
   float: right;
   margin-right: 4px;
   padding: 9px 15px;
   margin-top: 43px;
}



/* ------- COLOR, TYPOGRAPHY ------ */


body {
   font-size: 14px;
   font-family: 'Source Sans Pro', sans-serif;
   background-color: rgb(236, 214, 173);
}

.card {
   box-shadow: 2px 2px 15px rgb(167, 131, 131);
   background-color: white;
   padding: 25px;
}

h2 {
   font-size: 44px;
   font-family: 'Leckerli One', cursive;
   text-align: center;
}

/* the is-loading class is set/removed by JavaScript */
#photo-viewer.is-loading::after {
   content: url('https://retchhh.files.wordpress.com/2015/03/loading1.gif?w=300&h=300');
   position: absolute;
   top: 0;
   right: 0;
}

#photo-viewer img {
   position: absolute;
   max-width: 100%;
   max-height: 100%;
   top: 50%;
   left: 50%;
}

.info {
   padding: 12px 0px 12px 12px;
}

.info strong {
   font-weight: bold;
}

.info p {
   margin-bottom: 7px;
}

.info li {
   list-style-type: square;
   list-style-position: inside;
}

.actions {
   padding-top: 10px;
}

a.thumb {
   text-decoration: none;
}

/* the active class is set/removed by JavaScript */
a.thumb.active {
   opacity: 0.3;
}

.actions button {
   padding: 9px 15px;
   background-color: tomato;
   border: none;
   color: rgb(240,240,210);
}
              
            
!

JS

              
                /////////////////////////////////
// global variables
var lastRequested; //URL of the last image to be requested
var $currentImg; //current image being shown
var cache = {}; //empty cache object
var $frame = $('#photo-viewer'); //image frame div
var $thumbs = $('.thumb'); //the thumbnails links


/////////////////////////////////
// function to fade from the current image to a specified image
// pass in new image as parameter
function crossfade($newImg) {
   
   // if there is currently an image showing
   if($currentImg) {
      //stop its animation and fade it out
      $currentImg.stop().fadeOut('slow');
   }
   
   // apply css to the new image
   // the stylesheet has positioned it to top: 50% and left: 50%
   // now we're moving it back up and back left the appropriate amount to center it
   $newImg.css({
      //a negative margin of half its width
      marginLeft: (-$newImg.width()) / 2,
      //a negative margin of half its height
      marginTop: (-$newImg.height()) / 2
   });
   
   // stop any animation and fade the new image in
   $newImg.stop().fadeTo('slow', 1);
   
   // update the global variable
   // the new image is now the currently shown image
   $currentImg = $newImg; 
   
}


/////////////////////////////////
// all the actions to take when a thumbnail is cliked

// when a thumbnail is clicked, run the anonymous function
$(document).on('click', '.thumb', function(e) {
   
   //local variable for new image
   var $newImg; 
   //"this" is the thumbnail anchor link
   //so local variable src holds the href of the clicked anchor link
   var src = this.href;
   //store as a global variable
   //the URL of the latest image to be requested
   lastRequested = src;
   
   //prevent the default link behavior
   e.preventDefault();
   
   //remove active class from all thumbnails
   $thumbs.removeClass('active');
   //add active class to the thumnail that was clicked
   $(this).addClass('active');
   
   //if the cache object contains this src URL 
   if(cache.hasOwnProperty(src)) {
      //and if that image is not currently loading
      if(cache[src].isLoading === false) {
         //crossfade to the cached image
         crossfade(cache[src].$img);
         }
   } else { //otherwise it's not in the cache
      $img = $('<img/>'); //set $img to be an empty img element
      //store this image as an object in the cache, named by the URL
      cache[src] = {
         //store the empty img element
         $img: $img,
         // set isLoading property to true
         isLoading: true
      };
   
   //specify what should happen WHEN the image has loaded (it's not yet)
   $img.on('load', function() {
      //hide the just-loaded image
      $img.hide(); 
      //remove the is-loading class from the image frame div
      //append the newly-loaded image to the frame div
      $frame.removeClass('is-loading').append($img);
      //now it's finished, so remove isLoading status in the cache
      cache[src].isLoading = false;
      //check that this is still the last requested image
      if(lastRequested === src) {
         //crossfade to this image
         crossfade($img);
         }
   });
   
   //add the is-loading class to the frame div
   $frame.addClass('is-loading');
   
   //set attributes on the img element
   $img.attr({
      'src': src, //set its src attribute to the URL
      'alt': this.title || '' //if the image has a title, add it to the alt attribute, otherwise set the attribute to be null
   });
   
 }
   
});


/////////////////////////////////
//once the script has loaded
//run this line to initiate the first image as the active one
//by simulating a click on it
$('.thumb').eq(0).click();
              
            
!
999px

Console