Linkvoorbeeld bij hover Nieuw
Links in een blogtekst tonen bij hover of toetsenbordfocus een klein voorbeeld van de pagina: foto, adres, titel en één regel uitleg. Opent met een korte vertraging, blijft open als je naar het kaartje beweegt, sluit met Esc en blijft altijd binnen het tekstvlak. Voor interne links in blogs, kennisbanken en projectverhalen.
Verbouwen in 2026: waar begin je?
Begin bij wat het meeste oplevert. Lees hoe we een badkamer in Delft in drie weken vernieuwden, wat een hybride warmtepomp in Zwolle kostte en waarom Fysio Oost in Utrecht koos voor één open behandelruimte.
Zo gebruik je het
- Plak de HTML op de plek waar het onderdeel moet komen.
- Zet de CSS in je stylesheet. Alle klassen hebben een eigen voorvoegsel, dus niets botst met je eigen opmaak.
- Voeg de JavaScript toe en roep init() aan met het element waar de HTML in staat.
<!-- Linkvoorbeeld bij hover · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="lvh">
<div class="lvh__art">
<h3 class="lvh__h">Verbouwen in 2026: waar begin je?</h3>
<p class="lvh__p">Begin bij wat het meeste oplevert. Lees hoe we <a class="lvh__a" href="#linkvoorbeeld-hover" data-i="0">een badkamer in Delft</a> in drie weken vernieuwden, wat <a class="lvh__a" href="#linkvoorbeeld-hover" data-i="1">een hybride warmtepomp in Zwolle</a> kostte en waarom <a class="lvh__a" href="#linkvoorbeeld-hover" data-i="2">Fysio Oost in Utrecht</a> koos voor één open behandelruimte.</p>
</div>
<div class="lvh__card" id="lvh-card" role="tooltip" hidden>
<img class="lvh__img" src="https://neddev.com/lab-media/linkvoorbeeld-hover-1.webp" alt="" width="800" height="436">
<div class="lvh__body"><p class="lvh__url"></p><p class="lvh__t"></p><p class="lvh__x"></p></div>
</div>
</div>
</div>/* Linkvoorbeeld bij hover · NedDev · eigen werk. */
.lvh{position:absolute;inset:0;padding:16px 18px;font-family:'Switzer',system-ui,sans-serif;color:#0a0a0a;background:#fff;text-align:left;overflow:hidden}
.lvh *{box-sizing:border-box}
.lvh__art{max-width:400px}
.lvh__h{margin:0 0 8px;font-size:17px;line-height:1.2;font-weight:700;letter-spacing:-.015em}
.lvh__p{margin:0;font-size:13.5px;line-height:1.6;color:#2a2a2a}
.lvh__a{color:#0a0a0a;font-weight:600;text-decoration:underline;text-decoration-color:#F5480F;text-decoration-thickness:2px;text-underline-offset:3px;border-radius:2px}
.lvh__a:hover{background:#fde6dc}
.lvh__a:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.lvh__card{position:absolute;left:0;top:0;width:224px;background:#fff;border:1px solid #0a0a0a;border-radius:8px;overflow:hidden;box-shadow:0 14px 28px -14px rgba(10,10,10,.45);opacity:0;transform:translateY(4px);transition:opacity .16s,transform .16s;pointer-events:auto;z-index:5}
.lvh__card.is-on{opacity:1;transform:none}
.lvh__card:not(.is-on){pointer-events:none}
.lvh__card[hidden]{display:none}
.lvh__img{display:block;width:100%;height:78px;object-fit:cover;background:#f4f3f1}
.lvh__body{padding:8px 10px 10px}
.lvh__url{margin:0;font-size:12px;color:#5b5b5b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lvh__t{margin:2px 0 0;font-size:13px;line-height:1.25;font-weight:700}
.lvh__x{margin:3px 0 0;font-size:12px;line-height:1.35;color:#3a3a3a}
@media (prefers-reduced-motion:reduce){.lvh__card{transition:none;transform:none}}// Linkvoorbeeld bij hover · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
var w = root.querySelector('.lvh'), card = w.querySelector('.lvh__card'), img = card.querySelector('.lvh__img');
var uEl = card.querySelector('.lvh__url'), tEl = card.querySelector('.lvh__t'), xEl = card.querySelector('.lvh__x');
var base = img.getAttribute('src').replace(/linkvoorbeeld-hover-1\.webp$/, '');
var P = [
['voorbeeld.nl/projecten/badkamer-delft', 'Badkamer in Delft, klaar in drie weken', 'Inloopdouche, zwevend meubel en vloerverwarming.', 'linkvoorbeeld-hover-1.webp'],
['voorbeeld.nl/blog/hybride-warmtepomp-kosten', 'Wat kost een hybride warmtepomp?', 'Rekenvoorbeeld uit Zwolle: € 4.850, na subsidie € 2.725.', 'linkvoorbeeld-hover-2.webp'],
['voorbeeld.nl/projecten/fysio-oost-utrecht', 'Fysio Oost: één open behandelruimte', 'Van vier kleine kamers naar één lichte ruimte.', 'linkvoorbeeld-hover-3.webp']
];
P.forEach(function (p) { var i = new Image(); i.src = base + p[3]; });
var links = [].slice.call(w.querySelectorAll('.lvh__a')), cur = null, tOpen = 0, tClose = 0;
var rm = matchMedia('(prefers-reduced-motion: reduce)').matches;
function place(a) {
var W = w.clientWidth, H = w.clientHeight, wr = w.getBoundingClientRect();
var rs = a.getClientRects(), r = rs[0];
var cw = card.offsetWidth, ch = card.offsetHeight;
var left = r.left - wr.left + r.width / 2 - cw / 2;
left = Math.max(6, Math.min(W - cw - 6, left));
var below = rs[rs.length - 1].bottom - wr.top + 6, above = r.top - wr.top - ch - 6, top;
if (below + ch <= H - 6) top = below; else if (above >= 6) top = above; else top = Math.max(6, H - ch - 6);
card.style.left = left + 'px'; card.style.top = top + 'px';
}
function show(a) {
clearTimeout(tClose);
var p = P[+a.dataset.i];
if (cur !== a) {
img.src = base + p[3]; uEl.textContent = p[0]; tEl.textContent = p[1]; xEl.textContent = p[2];
if (cur) cur.removeAttribute('aria-describedby');
}
cur = a; a.setAttribute('aria-describedby', 'lvh-card');
card.hidden = false; place(a);
requestAnimationFrame(function () { card.classList.add('is-on'); });
}
function hide() {
clearTimeout(tOpen); card.classList.remove('is-on');
if (cur) cur.removeAttribute('aria-describedby');
cur = null;
tClose = setTimeout(function () { if (!cur) card.hidden = true; }, rm ? 0 : 170);
}
links.forEach(function (a) {
a.addEventListener('mouseenter', function () { clearTimeout(tOpen); clearTimeout(tClose); tOpen = setTimeout(function () { show(a); }, cur ? 0 : 300); });
a.addEventListener('mouseleave', function () { clearTimeout(tOpen); tClose = setTimeout(hide, 160); });
a.addEventListener('focus', function () { show(a); });
a.addEventListener('blur', function () { hide(); });
a.addEventListener('click', function (e) { e.preventDefault(); });
});
card.addEventListener('mouseenter', function () { if (cur) clearTimeout(tClose); });
card.addEventListener('mouseleave', function () { tClose = setTimeout(hide, 160); });
w.addEventListener('keydown', function (e) { if (e.key === 'Escape' && cur) { hide(); } });
// voorbeeldstand in het Lab: het eerste kaartje staat open tot de eerste interactie
if (w.clientWidth >= 380 && matchMedia('(hover: hover)').matches) show(links[0]);
w.addEventListener('pointerenter', function once() { w.removeEventListener('pointerenter', once); if (document.activeElement !== links[0]) hide(); });
}
init(document.querySelector('.jouw-container'));
Meer uit componenten
Iets gezien dat je mooi vindt?
Zet het in je selectie en stuur hem op. Dan bouwen we je site eromheen, in jouw huisstijl.
Neem contact op →