JSFiddle - React, Tailwind, and code Playground
by Craig Martin
HTML
<img id="gridimg" src= "https://images.pexels.com/photos/66997/pexels-photo-66997.jpeg"/>
CSS
.splitting-image {
background-size: 0% 0%;
position: relative;
overflow: hidden;
}
.splitting-image img {
display: block;
}
@supports (--row-size: calc( 100% / 2 )) {
.splitting-image {
background-size: cover;
visibility: hidden;
--row-size: calc(100% / var(--row-total));
--col-size: calc(100% / var(--col-total));
--center-x: calc((var(--col-total) - 1) / 2);
--center-y: calc((var(--row-total) - 1) / 2);
}
.split-cell {
background: inherit;
position: absolute;
overflow: hidden;
top: calc(var(--row-size) * var(--row-index));
left: calc(var(--col-size) * var(--col-index));
width: calc(0.5px + var(--col-size));
height: calc(0.5px + var(--row-size));
/* Offset from center, positive & negative */
--offset-x: calc(var(--col-index) - var(--center-x));
--offset-y: calc(var(--row-index) - var(--center-y));
/* Absolute distance from center, only positive */
--distance-x: calc(
(var(--offset-x) * var(--offset-x)) / var(--center-x)
);
/* Absolute distance from center, only positive */
--distance-y: calc(
(var(--offset-y) * var(--offset-y)) / var(--center-y)
);
}
.split-cell__inner {
position: absolute;
visibility: visible;
background: inherit;
width: calc(100% * var(--col-total));
height: calc(100% * var(--row-total));
transform: translate(
calc(-1 * var(--col-size) * var(--col-index)),
calc(-1 * var(--row-size) * var(--row-index))
);
}
}
JavaScript
/**
* # SplittingImage
*
* @param {*} els
*/
function SplittingImage(els, opts) {
opts = opts || {};
return $(els).map(function(el, i) {
if (!el._splitImg) {
el._splitImg = split(el, opts);
if (el.classList) {
el.classList.add("splitting-image");
}
}
return el._splitImg;
});
}
/**
* # SplittingImage.$
* Convert selector or NodeList to array for easier manipulation.
*
* @param {*} els - Elements or selector
*/
function $(els) {
return Array.prototype.slice.call(
els.nodeName
? [els]
: els[0].nodeName ? els : document.querySelectorAll(els),
0
);
}
SplittingImage.$ = $;
/**
* # SplittingImage.split
* Split an element with the specified number of rows & cols
* @param {Node} el - Element to split
* @param {String} key -
* @param {String|RegEx} splitBy - string or regex to split the innerText by
* @param {Boolean} space - Add a space to each split if index is greater than 0. Mainly for `Splitting.words`
*/
function split(el, opts) {
var img =
opts.image || (el.dataset && el.dataset.image) || el.currentSrc || el.src,
rows = opts.rows || (el.dataset && el.dataset.rows) || 1,
cols = opts.cols || (el.dataset && el.dataset.cols) || 1,
row = 0,
col = 0,
cells = [],
parent = el.parentNode,
cell,
inner,
temp;
// Use fragment to prevent unnecessary DOM thrashing.
var fragment = document.createDocumentFragment();
for (; row < rows; row++) {
for (col = 0; col < cols; col++) {
// Create a span
cell = document.createElement("span");
cell.className = "split-cell";
cell.style.setProperty("--row-index", row);
cell.style.setProperty("--col-index", col);
cell.style.setProperty("--cell-index", cells.length);
cell.setAttribute("data-row", row);
cell.setAttribute("data-col", col);
inner = document.createElement("span");
inner.className = "split-cell__inner";
...