I recently needed to modernise a slideshow created by different tabs hosting images that then used a tab revolver by creating a dynamic slideshow that would automatically display all images from the same folder as my ASP.NET page. The requirements were quite specific: full-screen display, automatic detection of new images without page refresh, configurable timing between slides, and smooth professional transitions.
Requirements
The slideshow needed to:
- Display all images from the current folder in full-screen mode
- Automatically scan for newly added or removed images without requiring a page refresh
- Use a configurable variable to control the timeout between slides
- Provide smooth, professional transitions between images
- Work on an IIS server with ASP.NET support
Simple Solution
I developed a single-file solution using ASP.NET that combines both the slideshow display and the server-side image scanning in one index-autorefresh.aspx file. This approach keeps everything simple while providing all the required functionality.
Key Features Implemented
1. Configurable Timing Variables
I made the slideshow timing easily adjustable with clear configuration variables:
// Configuration
const SLIDE_DURATION = 15000; // 15 seconds between slides
const FADE_DURATION = 1500; // 1.5 seconds fade transition
const CHECK_INTERVAL = 5000; // Check for new images every 5 seconds
This approach allows me to quickly modify timing without hunting through the code.
2. Professional Fade Transitions
Instead of abrupt show/hide transitions, I implemented smooth CSS-based fade effects:
.slide {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 1.5s ease-in-out;
}
.slide.active {
opacity: 1;
}
The slides are positioned absolutely and overlay each other, with opacity transitions creating a cinematic fade effect.
3. Full-Screen Display
I achieved true full-screen presentation by making the container cover the full avaliable window, with the browser in F11 mode:
.slideshow-container {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
overflow: hidden;
}
Images use object-fit: to fill the screen completely while maintaining aspect ratio.
5. Smart Update Logic
When changes are detected, the slideshow updates seamlessly without interrupting the current flow:
if (JSON.stringify(newImages.sort()) !== JSON.stringify(currentImages.sort())) {
console.log('Images updated - refreshing slideshow');
updateSlideshow(newImages);
if (newImages.length > 1) {
clearTimeout(slideTimer);
slideTimer = setTimeout(showSlidesAuto, SLIDE_DURATION);
}
}
I use JSON string comparison to detect changes and sort the arrays to handle reordering gracefully.
Server-Side Image Scanning
The ASP.NET page dynamically scans for image files using the following logic:
<%
string[] allowedExtensions = {".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"};
string currentPath = Server.MapPath(".");
string[] files = Directory.GetFiles(currentPath);
for (int i = 0; i < files.Length; i++)
{
string fileName = Path.GetFileName(files[i]);
string extension = Path.GetExtension(fileName).ToLower();
if (Array.IndexOf(allowedExtensions, extension) >= 0)
{
Response.Write("\"" + fileName + "\"");
// Add comma if more images follow
}
}
%>
This scans the current directory and filters for common image formats, if you have other you may need to add them to that code!
Smooth Transition Logic
The transition logic maintains timing consistency while providing smooth visual flow:
function showSlidesAuto() {
if (slides.length <= 1) {
slideTimer = setTimeout(showSlidesAuto, SLIDE_DURATION);
return;
}
slides[slideIndex].classList.remove("active");
slideIndex = (slideIndex + 1) % slides.length;
slides[slideIndex].classList.add("active");
slideTimer = setTimeout(showSlidesAuto, SLIDE_DURATION);
}
Script : index-autorefresh.aspx
<%@ Page Language="C#" %>
<%@ Import Namespace="System.IO" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Auto Slideshow</title>
<style>
body {
margin: 0;
background: #111;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.slideshow-container {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
overflow: hidden;
}
.slide {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 1.5s ease-in-out;
}
.slide.active {
opacity: 1;
}
.slide img {
width: 100%;
height: 100%;
object-fit: cover;
background: #000;
}
</style>
</head>
<body>
<div class="slideshow-container" id="slideshow"></div>
<script>
// Images dynamically generated from server
const images = [
<%
string[] allowedExtensions = {".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"};
string currentPath = Server.MapPath(".");
string[] files = Directory.GetFiles(currentPath);
for (int i = 0; i < files.Length; i++)
{
string fileName = Path.GetFileName(files[i]);
string extension = Path.GetExtension(fileName).ToLower();
if (Array.IndexOf(allowedExtensions, extension) >= 0)
{
Response.Write("\"" + fileName + "\"");
if (i < files.Length - 1)
{
// Check if there are more image files coming
bool hasMoreImages = false;
for (int j = i + 1; j < files.Length; j++)
{
string nextExt = Path.GetExtension(Path.GetFileName(files[j])).ToLower();
if (Array.IndexOf(allowedExtensions, nextExt) >= 0)
{
hasMoreImages = true;
break;
}
}
if (hasMoreImages) Response.Write(",\n ");
}
}
}
%>
];
// Configuration
const SLIDE_DURATION = 15000; // 15 seconds between slides
const FADE_DURATION = 1500; // 1.5 seconds fade transition
const CHECK_INTERVAL = 5000; // Check for new images every 5 seconds
let slideIndex = 0;
let currentImages = [];
let slides = [];
let slideTimer = null;
const container = document.getElementById("slideshow");
// Get current images from server (reloads the same page)
async function getCurrentImages() {
try {
const response = await fetch(window.location.href + '?t=' + Date.now());
const text = await response.text();
// Extract image array from the server response
const match = text.match(/const images = \[([\s\S]*?)\];/);
if (match) {
const imageStr = match[1];
const imageArray = imageStr.split(',').map(s => s.trim().replace(/['"]/g, ''));
return imageArray.filter(img => img.length > 0);
}
return [];
} catch (error) {
console.error('Error checking for images:', error);
return currentImages;
}
}
// Update slideshow with new images
function updateSlideshow(newImages) {
// Clear existing slides
container.innerHTML = '';
if (newImages.length === 0) {
container.innerHTML = '<div style="color: white; text-align: center; line-height: 100vh;">No images found</div>';
return;
}
// Create new slide elements
newImages.forEach((src, index) => {
let div = document.createElement("div");
div.classList.add("slide");
if (index === slideIndex % newImages.length) div.classList.add("active");
let img = document.createElement("img");
img.src = src + '?t=' + Date.now(); // Cache busting for updated images
div.appendChild(img);
container.appendChild(div);
});
slides = document.querySelectorAll(".slide");
// Adjust slideIndex if it's beyond the new array length
if (slideIndex >= newImages.length && newImages.length > 0) {
slideIndex = 0;
slides[0].classList.add("active");
}
currentImages = newImages;
}
// Check for image changes
async function checkForChanges() {
const newImages = await getCurrentImages();
// Compare arrays to see if they've changed
if (JSON.stringify(newImages.sort()) !== JSON.stringify(currentImages.sort())) {
console.log('Images updated - refreshing slideshow');
updateSlideshow(newImages);
// Restart slideshow if we have images
if (newImages.length > 1) {
clearTimeout(slideTimer);
slideTimer = setTimeout(showSlidesAuto, SLIDE_DURATION);
}
}
// Schedule next check
setTimeout(checkForChanges, CHECK_INTERVAL);
}
function showSlidesAuto() {
if (slides.length <= 1) {
slideTimer = setTimeout(showSlidesAuto, SLIDE_DURATION);
return;
}
// Remove active class from current slide
slides[slideIndex].classList.remove("active");
// Move to next slide
slideIndex = (slideIndex + 1) % slides.length;
// Add active class to new slide
slides[slideIndex].classList.add("active");
// Schedule next transition
slideTimer = setTimeout(showSlidesAuto, SLIDE_DURATION);
}
// Initialize slideshow with server-generated list first
updateSlideshow(images);
if (images.length > 1) {
slideTimer = setTimeout(showSlidesAuto, SLIDE_DURATION);
}
// Start checking for changes after initial load
setTimeout(checkForChanges, CHECK_INTERVAL);
</script>
</body>
</html>
Usage
- Place the code above in a file in the same directory as your images (using UTF-8 encoding)
- Ensure your IIS server has ASP.NET enabled
- Add or remove images from the folder - they'll appear/disappear automatically within 5 seconds
The solution provides a professional, maintenance-free slideshow that adapts to content changes in real-time, perfect for digital signage or presentation scenarios where content updates frequently.