Search code examples
cssmaterial-uilinethinborder-radius

Iframe on applying border radius have thin curve lines on the 4 corners


I am using material UI's CardMedia component to render an Iframe where I have embedded a youtube link. I want the iframe to have rounded corners so I have set the border-radius to 30px. It's working, but the problem is that it also brings some thin lines on all four edges like the image below.

enter image description here

I have set border-width to 0. I tried making the border color to white or transparent but nothing works. Something iframe brings it in while I am applying border radius. It is mostly noted on Windows-based Browsers. However, it is not there in Mac's Chrome and Safari, other than that Firefox have this issue.

I am applying the styles to the CardMedia component via the sx prop. Here is my current code for it:

cardContainer: {
    height: '360px',
    maxWidth: '640px',
    borderRadius: '30px',
    webkitBorderRadius: '30px',
    mozBorderRadius: '30px',
    borderWidth: '0',
}

Here is a JS Fiddle with a live example on a white video: skip about a minute in the embedded video and check the edges. JS Fiddle Link

If you don't want to open up any external links, below is the code sample for you guys.

.custom {
    height: 360px;
    width: 640px;
    border-radius: 30px;
    border-width: 0;
}
<!DOCTYPE html>
<html>
<body>

<h1>The iframe element</h1>

<iframe class="custom" src="https://www.youtube.com/embed/OtVUZGhAHBc" title="lines on Iframe curves">
</iframe>

</body>
</html>


Solution

  • Issue:

    The reason behind the curve lines looks to be some default styling from youtube combined with some very small spacing left by the browser. If you inspect the iframe you find that inside your iframe you have the following styling:

    body {
      ...
      background-color: #000;
      ...
    }
    

    and

    .html5-video-player:not(.ytp-transparent), .html5-video-player.unstarted-mode, .html5-video-player.ad-showing, .html5-video-player.ended-mode, .html5-video-player.ytp-fullscreen {
      background-color: #000;
    }
    

    This 2 black backgrounds are basically the thin curve lines on the 4 corners. If you search and remove them from the browser inspector the lines will disappear.

    However I am afraid there isn't a simple solution to this since you can't edit the iframe styling anymore (an related question would be this one), and youtube somehow renders it's body just on the visible side of your container always. And if you have border radius this will result in the same outcome -> including if you load a bigger container inside a smaller one like this:

    .custom-wrapper {
        width: 635px;
        height: 355px;
        border-radius: 30px;
        overflow: hidden;
        position: relative;
        margin: 20px
    }
    .custom {
        width: 655px;
        height: 375px;
        position: absolute;
        top: -10px;
        left: -10px;
        overflow: visible
    }
    .custom iframe {
      width: 100%;
      height: 100%;
    }
    <h1>The iframe element</h1>
    
    
    <div class="custom-wrapper">
    <div class="custom">
    
    <iframe src="https://www.youtube.com/embed/OtVUZGhAHBc" title="lines on Iframe curves">
    </iframe>
    </div>
    </div>


    Solution / Alternative option:

    What you can try to do instead if creating an artificial border radius which won't affect how the iframe is loaded. Something like:

    .custom {
      margin: 20px;
      height: 360px;
      width: 640px;
      position: relative;
    }
    
    .custom::before {
      content: "";
      position: absolute;
      border-radius: 50px;
      padding: 20px;
      background: linear-gradient(45deg, #fff, #fff);
      -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
      mask-composite: add, add;
      -webkit-mask-composite: xor;
      mask-composite: exclude;
      inset: -15px;
      z-index: 999;
      width: calc(100% - 5px);
      height: calc(100% - 5px);
      pointer-events: none;
    }
    <h1>The iframe element</h1>
    <div class="custom">
      <iframe width="640px" height="360px" src="https://www.youtube.com/embed/OtVUZGhAHBc" title="lines on Iframe curves">
      </iframe>
      <div class="white-bg"></div>
    </div>


    Explanation:

    Basically we added a container for the iframe (positioned relative) and inside it also added a :before element which will act like the border radius we want.

    You can read more about the artificial border radius approach here but basically what this does is:

    1. From the link:

    • Appling a gradient as background and we make its origin the border box (by default it's the padding box).
    • Using the mask property, we apply two opaque layers. The bottom one will cover the whole element and the top one will cover only the padding box (so it will not cover the border area)
    • Excluded the top layer from the bottom one so that only the border area will be shown
    • Some browsers still don't support mask-composite so we use the prefixed version.

    2. Extra:

    • Since in this case we want to make the border only round the corners we have it inset: -15px; (or top: -15px; left: -15px;) and width: calc(100% - 5px); height: calc(100% - 5px); . This prevent any margin from being displayed.

    PS: You might want to play a little with this values since they might not be perfect, but the look pretty close to your requirements. Basically if you make the width and height bigger it would trim more but in this case you need to reposition the :before element. If you get any lines you don't want on the edges just make the container smaller or move it slightly so the :before elements covers them.

    • border-radius: 50px -> you wanted 30, but this is not a real border radius so 30 won't perfectly match your case. However you can also play with this value.

    • z-index: 999 this can be changed but basically a big index to position the element over the iframe. Also added pointer-events: none; to enable click on the iframe (so use the youtube window).

    • changed the colours for the background and the gradient to white (#fff) -> if you have another bg this should match the other one.

    • also increased the padding to 20px to be easier to hide the corners.