<div class="cg-wrap">
<h3 class="cg-title">院内フォトギャラリー</h3>
<ul class="cg-grid">
<li class="cg-cell">
<button type="button" class="cg-thumb-btn" aria-label="待合室の写真を拡大表示">
<img class="cg-thumb" src="https://placehold.co/600x400/2f8f9d/ffffff?text=待合室" alt="待合室">
</button>
</li>
<li class="cg-cell">
<button type="button" class="cg-thumb-btn" aria-label="受付の写真を拡大表示">
<img class="cg-thumb" src="https://placehold.co/600x400/6b7280/ffffff?text=受付" alt="受付">
</button>
</li>
<li class="cg-cell">
<button type="button" class="cg-thumb-btn" aria-label="診察室の写真を拡大表示">
<img class="cg-thumb" src="https://placehold.co/600x400/cccccc/666666?text=診察室" alt="診察室">
</button>
</li>
<li class="cg-cell">
<button type="button" class="cg-thumb-btn" aria-label="検査室の写真を拡大表示">
<img class="cg-thumb" src="https://placehold.co/600x400/2f8f9d/ffffff?text=検査室" alt="検査室">
</button>
</li>
<li class="cg-cell">
<button type="button" class="cg-thumb-btn" aria-label="処置室の写真を拡大表示">
<img class="cg-thumb" src="https://placehold.co/600x400/6b7280/ffffff?text=処置室" alt="処置室">
</button>
</li>
<li class="cg-cell">
<button type="button" class="cg-thumb-btn" aria-label="外観の写真を拡大表示">
<img class="cg-thumb" src="https://placehold.co/600x400/cccccc/666666?text=外観" alt="外観">
</button>
</li>
</ul>
<div class="cg-lightbox" hidden>
<div class="cg-overlay"></div>
<div class="cg-dialog" role="dialog" aria-modal="true" aria-label="院内フォトギャラリー拡大表示">
<button type="button" class="cg-close" aria-label="閉じる">×</button>
<button type="button" class="cg-nav cg-prev" aria-label="前の写真">
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15 6L9 12L15 18" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</button>
<img class="cg-full" src="" alt="">
<button type="button" class="cg-nav cg-next" aria-label="次の写真">
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9 6L15 12L9 18" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</button>
</div>
</div>
</div>
.cg-wrap {
--cg-columns: 3; /* PC表示時の列数 */
font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
max-width: 960px;
margin: 0 auto;
box-sizing: border-box;
}
.cg-wrap * { box-sizing: border-box; }
.cg-title {
margin: 0 0 1.2em;
text-align: center;
font-size: 1.2rem;
font-weight: 700;
color: #2d3339;
letter-spacing: .06em;
}
.cg-grid {
list-style: none;
margin: 0;
padding: 0;
display: grid;
grid-template-columns: repeat(var(--cg-columns), 1fr);
gap: .8em;
}
.cg-cell { margin: 0; }
.cg-thumb-btn {
display: block;
width: 100%;
padding: 0;
border: none;
background: none;
border-radius: 10px;
overflow: hidden;
cursor: pointer;
line-height: 0;
box-shadow: 0 2px 10px rgba(0,0,0,.06);
transition: transform .18s ease, box-shadow .18s ease;
}
.cg-thumb-btn:hover,
.cg-thumb-btn:focus-visible {
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(0,0,0,.1);
outline: none;
}
.cg-thumb-btn:focus-visible {
outline: 2px solid #2f8f9d;
outline-offset: 2px;
}
.cg-thumb {
display: block;
width: 100%;
height: auto;
aspect-ratio: 3 / 2;
object-fit: cover;
}
/* ライトボックス */
.cg-lightbox {
position: fixed;
inset: 0;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
}
.cg-lightbox[hidden] { display: none; }
.cg-overlay {
position: absolute;
inset: 0;
background: rgba(20, 24, 28, .82);
}
.cg-dialog {
position: relative;
z-index: 1;
max-width: min(90vw, 920px);
max-height: 88vh;
display: flex;
align-items: center;
justify-content: center;
}
.cg-full {
display: block;
max-width: 100%;
max-height: 88vh;
border-radius: 8px;
opacity: 0;
transform: scale(.97);
transition: opacity .18s ease, transform .18s ease;
}
.cg-full.cg-loaded {
opacity: 1;
transform: scale(1);
}
.cg-close {
position: absolute;
top: -44px;
right: -6px;
appearance: none;
border: none;
background: rgba(255,255,255,.12);
color: #fff;
width: 36px;
height: 36px;
border-radius: 50%;
font-size: 1.4rem;
line-height: 1;
cursor: pointer;
transition: background-color .15s;
}
.cg-close:hover,
.cg-close:focus-visible {
background: rgba(255,255,255,.25);
outline: none;
}
.cg-nav {
position: absolute;
top: 50%;
transform: translateY(-50%);
appearance: none;
border: none;
background: rgba(255,255,255,.12);
color: #fff;
width: 44px;
height: 44px;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: background-color .15s;
}
.cg-nav:hover,
.cg-nav:focus-visible {
background: rgba(255,255,255,.25);
outline: none;
}
.cg-prev { left: -60px; }
.cg-next { right: -60px; }
@media (max-width: 900px) {
.cg-prev { left: 6px; }
.cg-next { right: 6px; }
.cg-close { top: 6px; right: 6px; }
}
@media (max-width: 720px) {
.cg-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 375px) {
.cg-grid { gap: .6em; }
.cg-nav { width: 38px; height: 38px; }
}
@media (prefers-reduced-motion: reduce) {
.cg-thumb-btn,
.cg-full {
transition: none;
}
}
(function () {
function ClinicGallery(root) {
this.root = root;
this.thumbBtns = Array.prototype.slice.call(root.querySelectorAll('.cg-thumb-btn'));
this.lightbox = root.querySelector('.cg-lightbox');
this.fullImg = root.querySelector('.cg-full');
this.closeBtn = root.querySelector('.cg-close');
this.overlay = root.querySelector('.cg-overlay');
this.prevBtn = root.querySelector('.cg-prev');
this.nextBtn = root.querySelector('.cg-next');
this.index = 0;
this.lastFocused = null;
if (!this.lightbox || this.thumbBtns.length === 0) return;
this.bindEvents();
}
ClinicGallery.prototype.open = function (index) {
this.index = index;
this.lastFocused = document.activeElement;
this.render();
this.lightbox.hidden = false;
if (this.closeBtn) this.closeBtn.focus();
document.addEventListener('keydown', this.onKeydown);
};
ClinicGallery.prototype.close = function () {
this.lightbox.hidden = true;
document.removeEventListener('keydown', this.onKeydown);
if (this.lastFocused && typeof this.lastFocused.focus === 'function') {
this.lastFocused.focus();
}
};
ClinicGallery.prototype.render = function () {
var self = this;
var btn = this.thumbBtns[this.index];
var img = btn ? btn.querySelector('.cg-thumb') : null;
if (!img || !this.fullImg) return;
this.fullImg.classList.remove('cg-loaded');
this.fullImg.src = img.src;
this.fullImg.alt = img.alt;
var markLoaded = function () {
self.fullImg.classList.add('cg-loaded');
};
if (this.fullImg.complete) {
markLoaded();
} else {
this.fullImg.addEventListener('load', markLoaded, { once: true });
}
};
ClinicGallery.prototype.goTo = function (index) {
var count = this.thumbBtns.length;
this.index = (index + count) % count;
this.render();
};
ClinicGallery.prototype.next = function () {
this.goTo(this.index + 1);
};
ClinicGallery.prototype.prev = function () {
this.goTo(this.index - 1);
};
ClinicGallery.prototype.bindEvents = function () {
var self = this;
this.thumbBtns.forEach(function (btn, i) {
btn.addEventListener('click', function () {
self.open(i);
});
});
if (this.closeBtn) {
this.closeBtn.addEventListener('click', function () {
self.close();
});
}
if (this.overlay) {
this.overlay.addEventListener('click', function () {
self.close();
});
}
if (this.prevBtn) {
this.prevBtn.addEventListener('click', function () {
self.prev();
});
}
if (this.nextBtn) {
this.nextBtn.addEventListener('click', function () {
self.next();
});
}
this.onKeydown = function (e) {
if (e.key === 'Escape') {
self.close();
} else if (e.key === 'ArrowLeft') {
self.prev();
} else if (e.key === 'ArrowRight') {
self.next();
}
};
};
document.querySelectorAll('.cg-wrap').forEach(function (root) {
new ClinicGallery(root);
});
})();