From 54211f4400bc1b2ed07781929980aae5645d8542 Mon Sep 17 00:00:00 2001 From: John Paul Ellis Date: Thu, 4 Sep 2025 22:04:53 -0700 Subject: [PATCH] Added difference overlay mode in image comparison. - Uses CSS for difference overlay - Spacebar keyboard shortcut toggle - VS Code Agent GPT-5 (Preview) Prompts: ``` I saw this great tool at: https://tools.simonwillison.net/image-resize-quality It is open source on Github, so I checked it out. The tool shows an image at different resolutions and compression quality levels. I want to make it easier to do a visual diff. I want to have a toggle for showing the each resolution/quality image overlayed inverse on top of the source image (matched to scale). So if the quality matched perfectly, the image would be black because they'd both cancel each other out. This will make seeing compression artifacts more obvious. I want the filtering done using just CSS. Any questions? ``` ``` That is a good start, but the two images aren't aligned correctly. Here is a screenshot of how it renders. ``` ``` How dark can we make the page background before the contrast with the black text is too low for WCAG? I was thinking of making it a more neutral background gray when the diff mode is on. ``` ``` Let's go with #777 background and #000 for color when the diff mode is active ``` ``` What do you mean the image containers no longer switch to dark scheme? ``` ``` Let's try making it #111 for the background color, and #CCC for the text color when it is in the overlay mode. ``` ``` That looks good. Add a keyboard shortcut to toggle on/off diff mode using the spacebar. ``` ``` The keyboard shortcut is working well. But now I noticed an issue with image sizing when turning it on and off. The images get bigger when the diff mode goes on. It looks like it is due to the max-width being set at 80% but only when the diff mode is off. That must work the same with diff mode on. ``` ``` The images aren't centered in the `.image-diff-wrapper` like they should be. ``` ``` That is working great. One last change I'd like. I'd like to use CSS styling (and some pseudo or real elements) so that the real checkbox is hidden and a iOS style toggle slider is there. I was thinking it could be one parent element (that is the next sibling of the checkbox) that is styled to have pill-esque dimensions. Inside that element is another element that is styled to be a circle with some space between it and the outside edge of its parent element. Make it so that the circle is aligned left/right inside its pill shaped parent depending on if the checkbox is checked or not. Make it so that the movement happens with a transition. Make the background color of the pill shaped parent different if it is on versus off. The circle should always be the same color. ``` --- image-resize-quality.html | 130 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 123 insertions(+), 7 deletions(-) diff --git a/image-resize-quality.html b/image-resize-quality.html index 3307f43..8a204f0 100644 --- a/image-resize-quality.html +++ b/image-resize-quality.html @@ -12,6 +12,51 @@ margin: 0 auto; padding: 20px; } + /* Toggle switch (iOS-style) */ + label.toggle { display:flex; align-items:center; gap:10px; font-weight:500; } + label.toggle input[type="checkbox"] { + position:absolute; + opacity:0; + width:1px; height:1px; margin:0; padding:0; overflow:hidden; + clip:rect(0 0 0 0); clip-path: inset(50%); + } + label.toggle .toggle-visual { + position:relative; + width:48px; height:26px; + background:#b3b3b3; + border-radius:1000px; + box-shadow: inset 0 0 0 1px rgba(0,0,0,0.25); + transition: background .25s ease; + flex-shrink:0; + } + label.toggle .toggle-visual .toggle-knob { + position:absolute; top:3px; left:3px; + width:20px; height:20px; + background:#ffffff; + border-radius:50%; + box-shadow: 0 1px 3px rgba(0,0,0,0.4); + transition: transform .25s ease; + } + label.toggle input[type="checkbox"]:checked + .toggle-visual { + background:#2aa7ff; + } + label.toggle input[type="checkbox"]:checked + .toggle-visual .toggle-knob { + transform: translateX(22px); + } + /* Focus outline */ + label.toggle input[type="checkbox"]:focus-visible + .toggle-visual { + outline:2px solid #005ea6; outline-offset:2px; + } + /* Dark background adjustments in diff mode */ + body.diff-mode label.toggle input[type="checkbox"]:focus-visible + .toggle-visual { + outline-color:#8fd2ff; + } + body.diff-mode label.toggle .toggle-visual { box-shadow: inset 0 0 0 1px rgba(255,255,255,0.25); } + body.diff-mode label.toggle input[type="checkbox"]:not(:checked) + .toggle-visual { background:#555; } + body.diff-mode .note { color:#888; } + #controls { margin-top: 16px; display:flex; gap:24px; align-items:center; flex-wrap:wrap; } + #controls label { cursor:pointer; } + .note { font-size: 0.85rem; color:#555; } /* Drop zone is a