Link Previews on Hover
Add live mini webpage previews to links on hover.
This demo shows how to add live mini-previews to links on hover in your Ghost site.
Check out this link to
Culture Solutions Group, one of my client's websites. Hover over it to see a small preview of what it points to.
And here is what the Wikipedia website mini-preview looks like...
Wikipedia.
And here is the
Elizabeth II page on Wikipedia.
Those previews were fetched as soon as this page loaded. This is great for having the previews ready ahead of time, but can eat up extra bandwidth.
As an alternative, check out these same links to Culture Solutions Group and Wikipedia and Elizabeth II. This time the previews aren't fetched until you hover over this paragraph.
Finally, check out these links again to Culture Solutions Group and Wikipedia and Elizabeth II. These previews are only fetched when needed (when you hover over the specific link.) This saves the most bandwidth on page load, but there will be a delay before the previews can be shown.
Put this in an HTML Card...
<p id="p1">
Check out this link to
<a href="https://culturesolutionsgroup.com">Culture Solutions Group</a>, one of my client's websites. Hover over it to see a small preview of what it points to.<br><br>
And here is what the Wikipedia website mini-preview looks like...
<a href="https://wikipedia.org">Wikipedia</a>.
<br><br>
And here is the
<a href="https://en.wikipedia.org/wiki/Elizabeth_II">Elizabeth II</a> page on Wikipedia.<br><br>
Those previews were fetched as soon as this page loaded. This is great for having the previews ready ahead of time, but can eat up extra bandwidth.
</p>
<p id="p2">
As an alternative, check out these same links to
<a href="https://culturesolutionsgroup.com">Culture Solutions Group</a> and
<a href="https://wikipedia.org">Wikipedia</a>
and
<a href="https://en.wikipedia.org/wiki/Elizabeth_II">Elizabeth II</a>. This time the previews aren't fetched until you hover over this paragraph.
</p>
<p id="p3">Finally, check out these links again to
<a href="https://culturesolutionsgroup.com">Culture Solutions Group</a> and
<a href="https://wikipedia.org">Wikipedia</a>
and
<a href="https://en.wikipedia.org/wiki/Elizabeth_II">Elizabeth II</a>. These previews are only fetched when needed (when you hover over the specific link.) This saves the most bandwidth on page load, but there will be a delay before the previews can be shown.
</p>
This goes in the Site (or Post) Header Injection...
<style>
.mini-preview-anchor {
display: inline-block;
position: relative;
white-space: nowrap;
}
.mini-preview-wrapper {
-moz-box-sizing: content-box;
box-sizing: content-box;
position: absolute;
overflow: hidden;
z-index: -1;
opacity: 0;
margin-top: -4px;
border: solid 1px #000;
box-shadow: 4px 4px 6px rgba(0, 0, 0, .3);
transition: z-index steps(1) .3s, opacity .3s, margin-top .3s;
}
.mini-preview-anchor:hover .mini-preview-wrapper {
z-index: 2;
opacity: 1;
margin-top: 6px;
transition: opacity .3s, margin-top .3s;
}
.mini-preview-loading, .mini-preview-cover {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
}
.mini-preview-loading {
display: table;
height: 100%;
width: 100%;
font-size: 1.25rem;
text-align: center;
color: #f5ead4;
background-color: #59513f;
}
.mini-preview-loading::before {
content: 'Loading...';
display: table-cell;
text-align: center;
vertical-align: middle;
}
.mini-preview-cover {
background-color: rgba(0, 0, 0, 0); /* IE fix */
}
.mini-preview-frame {
border: none;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
}
</style>
This goes in the Site (or Post) Footer Injection...
<script>
(function($) {
var PREFIX = 'mini-preview';
// implemented as a jQuery plugin
$.fn.miniPreview = function(options) {
return this.each(function() {
var $this = $(this);
var miniPreview = $this.data(PREFIX);
if (miniPreview) {
miniPreview.destroy();
}
miniPreview = new MiniPreview($this, options);
miniPreview.generate();
$this.data(PREFIX, miniPreview);
});
};
var MiniPreview = function($el, options) {
this.$el = $el;
this.$el.addClass(PREFIX + '-anchor');
this.options = $.extend({}, this.defaultOptions, options);
this.counter = MiniPreview.prototype.sharedCounter++;
};
MiniPreview.prototype = {
sharedCounter: 0,
defaultOptions: {
width: 256,
height: 144,
scale: .25,
prefetch: 'pageload'
},
generate: function() {
this.createElements();
this.setPrefetch();
},
createElements: function() {
var $wrapper = $('<div>', { class: PREFIX + '-wrapper' });
var $loading = $('<div>', { class: PREFIX + '-loading' });
var $frame = $('<iframe>', { class: PREFIX + '-frame' });
var $cover = $('<div>', { class: PREFIX + '-cover' });
$wrapper.appendTo(this.$el).append($loading, $frame, $cover);
// sizing
$wrapper.css({
width: this.options.width + 'px',
height: this.options.height + 'px'
});
// scaling
var inversePercent = 100 / this.options.scale;
$frame.css({
width: inversePercent + '%',
height: inversePercent + '%',
transform: 'scale(' + this.options.scale + ')'
});
// positioning
var fontSize = parseInt(this.$el.css('font-size').replace('px', ''), 10)
var top = (this.$el.height() + fontSize) / 2;
var left = (this.$el.width() - $wrapper.outerWidth()) / 2;
$wrapper.css({
top: top + 'px',
left: left + 'px'
});
},
setPrefetch: function() {
switch (this.options.prefetch) {
case 'pageload':
this.loadPreview();
break;
case 'parenthover':
this.$el.parent().one(this.getNamespacedEvent('mouseenter'),
this.loadPreview.bind(this));
break;
case 'none':
this.$el.one(this.getNamespacedEvent('mouseenter'),
this.loadPreview.bind(this));
break;
default:
throw 'Prefetch setting not recognized: ' + this.options.prefetch;
break;
}
},
loadPreview: function() {
this.$el.find('.' + PREFIX + '-frame')
.attr('src', this.$el.attr('href'))
.on('load', function() {
// some sites don't set their background color
$(this).css('background-color', '#fff');
});
},
getNamespacedEvent: function(event) {
return event + '.' + PREFIX + '_' + this.counter;
},
destroy: function() {
this.$el.removeClass(PREFIX + '-anchor');
this.$el.parent().off(this.getNamespacedEvent('mouseenter'));
this.$el.off(this.getNamespacedEvent('mouseenter'));
this.$el.find('.' + PREFIX + '-wrapper').remove();
}
};
})(jQuery);
</script>
<script>
$(function() {
$('#p1 a').miniPreview({ prefetch: 'pageload' });
$('#p2 a').miniPreview({ prefetch: 'parenthover' });
$('#p3 a').miniPreview({ prefetch: 'none' });
});
</script>
From:
If you have a lot of mini-previews on one page, and that page is loading too slowly, here is a modification you can make... https://github.com/lonekorean/mini-preview/issues/5
You can also find the source code and docs at... https://codegena.com/image-link-preview-on-hover/
And a supplementary modification... https://stackoverflow.com/questions/66701233/minipreview-jquery-link-preview-contents-of-parent-p-or-div-only