Adjusting the object-fit property to "contain" and combining it with border-radius or exploring other alternatives can enhance

My goal is to showcase videos on a webpage while utilizing border-radius to round the corners for a more aesthetically pleasing look.

The challenge arises as the videos come in varying aspect ratios, requiring them to be accommodated within containers without distorting their original proportions. With changing container and video dimensions over time, including potential resizing due to dynamic sources like getUserMedia or streaming, achieving a consistent and optimal display becomes complex.

In scenarios where the videos shrink too small, conventional methods like setting max-width and max-height fall short of satisfying the need to utilize all available space within the container effectively.

Upon exploration, it seems that using object-fit: contain offers the best solution for fitting videos into containers while preserving aspect ratios. However, compatibility issues with border-radius arise when the video fails to fully occupy the container.

Referring to an insightful answer, it suggests that a pure CSS approach might not address this specific issue. Thus, I seek clarification on whether this limitation still holds true.

To summarize the challenges faced:

  • Sole reliance on max-width and max-height proves ineffective when videos are undersized and require expansion within the container.
  • Despite its advantages, object-fit: contain encounters limitations when combined with border-radius under various circumstances.

Below presents a code snippet wherein JavaScript is employed to compare parent (border) and video aspect ratios, aiding in deciding between width: 100% or height: 100%. The CSS rules are externally defined through classnames.

// JavaScript component fetching and rendering videos
const DisplayVideo = ({
  videoSrc = null,
  // additional props
}) => {
  const videoRef = useRef(null);
  const borderRef = useRef(null);
  const [fillMode, setFillMode] = useState(''); // fill-width or fill-height

  useEffect(() => {
    // Play video if new source provided
    if (videoRef && videoRef.current && videoSrc) {
      if (videoRef.current.srcObject !== videoSrc) {
        videoRef.current.srcObject = videoSrc;
      }

      videoRef.current.play();
    }
  }, [videoRef, videoSrc]);

  useEffect(() => {
    // Determine fill mode based on aspect ratios
    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 content
    </div>
  );
};

const mapStateToProps = (state, ownProps) => {
  // mapping relevant data
  return { videoSrc: remoteVideoSrcs[mid] };
};

export default connect(mapStateToProps)(DisplayVideo);

An issue arises as the videoWidth and videoHeight values in the useEffect return as 0 during execution. Contrastingly, calling document.getElementsByClassName(...) from the console yields accurate values instead of 0. This anomaly potentially indicates unsuitability of useEffect placement. Considering redux triggers execution post-change in videoSrc only, how can the code be modified to reflect changes in videoWidth and videoHeight promptly?

Answer №1

To keep things simple, I'll refer to the function that compares the video and parent's aspect ratio and decides whether to constrain the video by height or width as "onResize."

When should we call onResize?

  1. When the video source changes dimensions
  2. When the parent changes dimensions

Simply calling onResize during useEffect (which happens after every render) is not enough.

The video element has an onresize event where we can invoke the comparison function. This method does not rely on waiting for re-renders like in useEffect, which is crucial since the video source could change dimensions at any time.

videoElement.onresize = onResize;

The parent container may change dimensions when the window resizes or due to other state changes in the app. We can add listeners to the main window's onresize event within useEffect when the component mounts.

 useEffect(() => {
   if (typeof window !== 'undefined') {
     window.addEventListener('resize', onResize);
   }

   return () => {
     if (typeof window !== 'undefined') {
       window.removeEventListener('resize', onResize);
     }
   };
 }, []);

Lastly, we still need onResize in a useEffect with dependencies on any state that affects the size of the parent container. In my scenario, the total number of videos to display on screen impacts the parent container dimensions. So, I include something similar to this:

useEffect(() => { onResize() }, [numberOfVideos]);

Answer №2

develop your video element import './videocomponent.css'; // Include the CSS file

const VideoElement = ({ videoSrc, title }) => {
  return (
    <div className="video-wrapper">
        <video controls>
           <source src={videoSrc} type="video/mp4" />
        Your browser does not support the video tag.
      </video>
      <h3>{title}</h3>
    </div>
  );
};

 utilize this styling for the video element 

/* src/components/VideoComponent.css */

.video-wrapper {
  flex: 1 1 45%; /* Allow container to grow and shrink, take full width in mobile */
  margin: 5px;
  text-align: center;
  border: 0px solid #ccc;
  border-radius: 10px;
  padding: 5px;
  border-radius: 0px;
  box-shadow: 0 0px 0px rgba(0, 0, 0, 0.1);
  background-color: #fff;
}

.video-wrapper h3 {
  margin-bottom: 10px;
  font-size: 18px;
  color: #333;
}

.video-wrapper video {
  width: 100%; /* Full width */
  height: auto; /* Maintain aspect ratio */
  border-radius: 8px;
}

@media (max-width: 721px) {
  .video-wrapper {
    width: 100%; /* Full width */
  height: auto; /* Maintain aspect ratio */
  border-radius: 8px;/* Center items horizontally */
  }
}

then create a primary video element and import the video component

import VideoElement from './VideoComponent';
import './mainvideocmponent.css'; // Ensure this CSS file handles layout
import DataSecurity from '../../assets/videos/Data Security- Protect your critical data (or else).mp4';

const MainVideoComponent = () => {
  const videos = [
    { id: 1, src: DataSecurity , title: 'Data Security   By: Jeff Crume - Distinguished Engineer - CTO - IBM' }
  ];

  return (
    
    <div className="main-video-component">
      <div className="video-list">
        {videos.map((video) => (
          <VideoElement key={video.id} videoSrc={video.src} title={video.title} />
        ))}
      </div>
    </div>
  );
};

export default MainVideoComponent;


customize your primary video element with css 

/* src/components/MainVideoComponent.css */

.main-video-component {
  padding: 5px;
  border: 0px solid #ccc;
      background-color: #fff;
}

.main-video-component h2 {
  margin-bottom: 10px;
  text-align: right;
}

.video-list {
  display: flex;
  flex-wrap: wrap;
  border-radius: 0.25rem;

  gap: 1px; /* Space between video elements */
  justify-content: right; /* Center items horizontally */
}

/* Responsive design for mobile devices */
@media (max-width: 721px) {
  .video-list {
    flex-direction: column; /* Stack video components vertically */
    align-items: center; /* Center items horizontally */
  }
}

Now you can implement it on any page you prefer. Remember to update the actual path of all files. Hopefully this helps 

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the process for modifying the heading color in Bootstrap's dark mode?

If you want to enable dark mode according to the Bootstrap documentation instructions, follow these steps: <html lang="en" data-bs-theme="dark"> <head> <link href="https://cdn.jsdelivr.net/npm/bootstrap/dist/css/bootstrap.min.css" rel= ...

Why does the Select2 Drop down eliminate the mandatory border color?

Within my application, I have implemented a feature where required fields are designated with a red border. To achieve this effect, I utilized the following CSS code: input[data-val-required], select[data-val-required] { border: 1px solid #EFA4A4 !imp ...

Best practices for customizing form controls in Material UI to appear as TextFields

I am currently in the process of creating a form that includes multiple TextField elements. Within this form, there are various other elements in addition to TextFields, but unfortunately they do not blend well with the TextFields in terms of appearance. Y ...

Struggling with CSS Flexbox when it comes to organizing rows and combining Table and Table Cells

I've been struggling to fix a CSS flex problem for hours. My goal is to make sure that the three boxes in each row have the same height. While I'm familiar with using flex, I suspect that floats may be the root of the issue. Even after clearing t ...

Mastering Instagram Automation: Techniques for Navigating the Lightbox with Selenium

I am in the process of developing a Python script that assists users in Instagram engagement groups by efficiently liking everyone's photo during each round. I am facing an issue where Selenium is unable to click on the first photo when I reach a user ...

Unable to simulate the response from a React hook with varying values for individual unit tests

Here is an example of my component: import { VFC } from 'react'; import { useParams } from 'react-router-dom'; export const MyComponent: VFC = () => { const { sourceTemplate } = useParams(); return ( <div> ...

Encountering a SyntaxError: Unexpected token when trying to run a React application

I encountered an issue with console.log while running my react app Below is the useEffect portion of my app: useEffect(() => { const fetchData = async () => { const result = await fetch(`/api/foodies/${name}`); const body = await res ...

The Enchanted URL Folder Name

Spent two painstaking hours dealing with this issue. It's incredibly frustrating. Struggling to load css files in PHP pages when the URL contains a folder named "adsq" Comparing two identical pages, only differing in the folder name: One works perf ...

Embracing the Power of Sass

I have recently revamped my portfolio website on Github Pages and now I am looking to integrate Sass for my upcoming Portfolio 2.0 project. Although I have worked with Sass before, setting it up from scratch is new to me. Currently, I have installed Sass ...

What is the best way to connect a ref to a stateless component in React?

I need help creating a stateless component with an input element that can be validated by the parent component. In my code snippet below, I'm facing an issue where the input ref is not being assigned to the parent's private _emailAddress propert ...

Tips for moving the position of a free action icon within a react material-table

How can I add a freeAction button to the top-left corner of my material-table? Here is an illustration of what I'm looking for: https://i.sstatic.net/uJwY0.png I believe this involves using component-overriding, but I am having trouble implementing ...

Issue with orientation change when using webkit-overflow-scrolling: touch;

I am currently facing an issue with a fixed position div that has a specified width. The problem arises when the content is long enough to require overflow in one device orientation (landscape), but not the other (portrait) - scrolling stops working if the ...

React: Create a collapsible table to showcase nested JSON data in a structured format

I have a JSON structure that is hierarchical and I am looking to showcase it in a collapsible and nested table format. Is there a React UI framework or plugin that can handle displaying hierarchical data with a slide bar for the "volume" field? And how wou ...

Create responsive div elements within a container

I am working on a layout that consists of an outer div with 5 inner divs nested within it. ------------------------------------ | <div title> | | <div value><div unit> | | <d ...

What is the best way to display monthly data in a stacked bar chart using Recharts?

My data is structured as follows: [ { "CarbonAmount": 120, "CarbonDescription": null, "Date": "2022-03-14" }, { "CarbonAmount": 140, "CarbonDescription": "Electricity", "Date": "2022-04-11" } ] I am aiming to format it ...

When working with React Native, encountering an issue where passing props using the Map function results in an error stating "undefined is not a function" near the section of code involving the

Hey there! I'm currently facing an issue with fetching data from my Sanity CMS and passing it as props to a child component. Interestingly, the same code worked perfectly on another screen, but here I seem to be encountering an error. Although the dat ...

Is there a way to identify the breakpoints of a header that has a changing number of menus?

I am currently designing a customizable header for a web application, where the admin has the ability to add or remove menus as desired. For instance: https://i.sstatic.net/37IeG.png Or https://i.sstatic.net/zbIPd.png The breakpoints for these two navigat ...

Using conditional logic to import components in React.js (Conditional import based on a condition)

I am fairly new to React and I am currently facing an issue with importing components based on a condition passed through props. Here is the render code snippet from my class: render() { if (this.props.social == 1) { const FacebookLogin = require(&apos ...

The visibility of overflow-y does not seem to be working properly when overflow-x is

https://i.sstatic.net/hihjC.png .iati-list-table { overflow-x: auto; overflow-y: visible; } When I apply overflow-visible, a scroll bar appears. But when I use overflowy-hidden, the tooltip is cropped. How can I set it so that overflow x is auto a ...

How can I turn off the Jumbotron specifically for mobile devices in Bootstrap 4?

I have implemented a jumbotron on my website to create a full-height page on desktop, but I would like to disable the jumbotron on the mobile version. The content inside the jumbotron is extending beyond the available space on mobile, causing overlap wit ...