I'm trying to display videos on a page, and I want to use border-radius to round the corners.
The videos themselves can be of varying aspect ratios, and I'm trying to fit them in containers while preserving their aspect ratios. Both the dimensions of the containers and videos may change over time. The videos in particular may shrink or increase in size due to the nature of their sources (getUserMedia/streaming).
Sometimes they become too small, meaning that simply setting max-width and max-height will not work as I want the videos to fill as much space as they can inside the container.
From what I understand and tested, object-fit: contain is the best method for fitting videos in containers while preserving aspect ratios but cannot be directly used with border-radius when the video fails to fill the whole element.
Based off of this answer, it appears that this isn't possible through pure CSS? Just to be sure, I'd like to know if this is still the case.
To summarize:
- max-width and max-height alone did not work because sometimes the video is too small and I need it to expand as much as possible within the container
- object-fit: contain did not work because it did not work with border-radius in various circumstances
Below is code where I'm testing out using JS to determine and compare aspect ratios of parent (border) and video so that I can decide whether to use width: 100% or height: 100%. The CSS are all defined based off of classnames in a separate file.
const DisplayVideo = ({
videoSrc = null,
// other props
}) => {
const videoRef = useRef(null);
const borderRef = useRef(null);
const [fillMode, setFillMode] = useState(''); // fill-width or fill-height
useEffect(() => {
if (videoRef && videoRef.current && videoSrc) {
if (videoRef.current.srcObject !== videoSrc) {
videoRef.current.srcObject = videoSrc;
}
videoRef.current.play();
}
}, [videoRef, videoSrc]);
useEffect(() => {
// setting fillMode code here
const video = videoRef.current;
const border = borderRef.current;
if (video && border) {
const vAspectRatio = video.videoWidth / video.videoHeight;
const bAspectRatio = border.clientWidth / border.clientHeight;
setFillMode((vAspectRatio > bAspectRatio) ? 'fill-width' : 'fill-height');
}
});
return (
<div className="display-video-wrapper" ref={borderRef}>
<video className={`display-video ${fillMode}`} ref={videoRef} />
// other stuff
</div>
);
};
const mapStateToProps = (state, ownProps) => {
// stuff
return { videoSrc: remoteVideoSrcs[mid] };
};
export default connect(mapStateToProps)(DisplayVideo);
The issue is that the videoWidth and videoHeight values in the useEffect are all 0 when it runs. When I go to the page's console and call document.getElementsByClassName(...) to access the same values, they are the correct values, not 0. Perhaps useEffect isn't the best place to put this code? Due to redux, it's only running after a different videoSrc is set. I want it to run whenever the values of videoWidth and videoHeight changes.