Skip to content

Instantly share code, notes, and snippets.

@prmichaelsen
Last active August 12, 2022 19:21
Show Gist options
  • Save prmichaelsen/9282495535281909df09f77e104f24c5 to your computer and use it in GitHub Desktop.
Save prmichaelsen/9282495535281909df09f77e104f24c5 to your computer and use it in GitHub Desktop.
renders an image element that dynamically updates its bottom margin s.t. it always has a total height that is some multiple of 1.5em
import React, {
useEffect, useRef,
useState, useCallback,
} from 'react';
export function useResize() {
const getSize = () => {
return {
width: window.innerWidth,
height: window.innerHeight
};
};
const [size, setSize] = useState(getSize);
const handleResize = useCallback(() => {
let ticking = false;
if (!ticking) {
window.requestAnimationFrame(() => {
setSize(getSize());
ticking = false;
});
ticking = true;
}
}, []);
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return size;
}
interface ImgProps {
title: string;
alt: string;
src: string;
}
const pixelsPerEm = function() {
const div = document.createElement('div');
div.style.fontSize = '14px';
div.style.lineHeight = '1.5';
div.style.height = '1.5em';
div.style.minHeight = '1.5em';
document.body.append(div);
const px = div.clientHeight;
document.body.removeChild(div);
return px;
};
export const Img = (props: ImgProps) => {
const { src, alt, title} = props;
const ref = useRef<HTMLImageElement>(null);
let [style, setStyle] =
useState<React.CSSProperties>({
width: '100%',
});
const size = useResize();
useEffect(() => {
if (ref.current) {
const rect = ref.current
.getBoundingClientRect();
const height_inPx = rect.height;
const pxPerEm = pixelsPerEm();
let m = 0;
const diff = height_inPx % pxPerEm;
if (diff > 0) {
m = height_inPx - diff;
}
setStyle({
...style,
marginBottom: `${pxPerEm - diff}px`
});
}
}, [ref, size.width]);
return (
<div style={{
position: 'relative',
width: '100%',
display: 'flex',
alignContent: 'center',
justifyContent: 'center',
}}>
<a href={src} style={{
marginLeft: 'auto',
marginRight: 'auto',
background: 'none',
}}>
<img
ref={ref}
src={src}
style={style}
title={title}
alt={alt}
/>
</a>
</div>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment