Gallery Sketch

by lhamilton

HTML

<html>
  <body>
    <div id="overlay"></div>
    <main id="gallery">
      <!-- Each img tag should have the following attributes:
        class="preview" (exactly as-is, used for CSS and JS)
        onclick="fullSize(event)" (exactly as-is, attaches the JS, capitalization important)
        id="uniquepicture" (CHANGE THIS - it just has to be different from all the others)
        src="relative/to/small.png" (CHANGE THIS - your locally hosted, tiny preview image for this specific gallery item)
        title="Optional tool tip text" (CHANGE THIS or remove it- this will show up on hover but doesn't do anything on a touch screen.)
        data-fullsrc="https://external.link/to/your/image.png" (CHANE THIS to the full-size image. Can be external to another site, as it will only load one at a time when requested.)
        data-title="Optional Image Title" (CHANGE THIS or remove it- this will show up in a heading font below your image)
        data-caption="Optional Image Caption" (CHANGE THIS) or remove it- this will show up below your image in the larger preview popup.
      -->
      <img
        class="preview" 
        onclick="fullSize(event)" 
        src="https://kph.neocities.org/img/tiling-ghosts-small.png" 
        title="My tiny tiling ghost chart for double-knitting" 
        id="ghostspic"
        data-fullsrc="https://kph.neocities.org/img/ghost_fo_black.jpg"
        data-title="Ghosts"
        data-caption="I originally made this for a witchy, ghosty friend as a combination jar cozy & scarf. Standard double-knitting makes a reversible fabric, so long as your pattern doesn't have anything that looks bad as a mirror image, where the background and foreground colors are flipped. I really like doing double-knitting. It makes a super squooshy fabric. This chart is also great as a tiling background, because I made it to wrap all the way around a knitted item. :)" />
      <img
        class="preview" 
        onclick="fullSize(event)" 
       ...

CSS

/* 
#lightbox {
  display: none;
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 2;
  transform: translate(-50%, -50%);
  background-color: black;
  border-color: lilac;
  border: 1px;
  border-radius: 6px;
  padding: 10px;
  color: #d9d9d9;
}
*/

#lightbox {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  min-height: 110%;
  padding: 0;
  margin: 0;
  /* If you want to remove the greyed-out overlay, remove the background-color line: */
  background-color: rgba(0, 0, 0, 0.5);
  display: none;
  z-index: 1;
  justify-content: center;
  align-items: center;
  flex-direction: column;
}
#fullsize {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background-color: black;
  border-color: lilac;
  border: 1px;
  border-radius: 6px;
  padding: 1em;
  color: #d9d9d9;
  gap: 0.5em;
}
body {
  min-height: 100vh;
  margin-bottom: 0;
  padding: 0;
}
html {
  margin-bottom: 0;
  padding: 0;
}

JavaScript

//User settings
var scalex = 0.8; //The maximum percentage of the viewport width the fullsize image can take up
var scaley = 1.2; //The maximum percentage of the viewport height the fullsize image can take up, set below 1 to allow any height. Can be higher than 1 to allow a small but limited amount of runoff.
var headlevel = 'h2' //The heading level for your optional image titles

//End settings!

//This is where we'll cache pre-loaded and -sized images.
var loadedImages = [];

//This hides the overlay that pops up when you view a full-sized image.
function minimize() {
	document.getElementById('fullsize').innerHTML = '';
  document.getElementById('lightbox').style.display = 'none';
  //document.getElementById('overlay').style.display = "none";
}

//You have to wait for an image to load in order to get its size, so we attach this basic "what size is it" function as an event handler later on.
function saveOrigDim(ev) {
	let id = ev.target.getAttribute('data-name');
	loadedImages[id].setAttribute('data-maxheight', loadedImages[id].height);
  loadedImages[id].setAttribute('data-maxwidth', loadedImages[id].width);
  resizeImage(loadedImages[id]);
}

//This resizes the image according to our global settings and the *current* viewport size (users can resize their window at any time!) so that the aspect ratio is maintained and it fits on the screen.
function resizeImage(img, rescaleBox = true) {
	let origWidth = img.getAttribute('data-maxwidth');
  let origHeight = img.getAttribute('data-maxheight');
  let aspectRatio = origWidth / origHeight;
  console.log(origWidth, origHeight);
  let maxWidth = Math.min(origWidth, window.innerWidth * scalex);
  let maxHeight = origHeight;
  if (scaley > 0) {
  	maxHeight = Math.min(origHeight, window.innerHeight * scaley);
  }
  if (rescaleBox) {
  	let children = document.getElementById('fullsize').childNodes;
    for (let i = 0; i < children.length; i++) {
      children[i].style.width = Math.min(maxWidth, maxHeight * aspectRatio)...