Search code examples
javascriptcssbackground-imagerounding-error

Gap appearing down the middle


To Reproduce, To be able to see the gap, the code has to be viewed in these viewports in Chromium based browsers. The gap does not appear in Firefox.

You can set it to different viewports inside jsitor.

Also, By increasing and decreasing the browser you're able to see the Gap in the snippet provided. I just checked.

enter image description here

Click Run, not update to test code:

Further investigating finds:

Gap Visible https://jsitor.com/ublt2Y43V8

enter image description here

With YouTube Code Removed, No Gap Visible. https://jsitor.com/XT3U947ICr

Is there a solution to fix this gap issue?

https://i.imgur.com/zPivkcI.png

Gap appearing down the middle

enter image description here

From The Snippet:

enter image description here

const cover = document.querySelector(".jacket");
(function manageCurtain() {
  "use strict";

  function hide(el) {
    el.classList.add("hide");
  }

  function coverClickHandler(evt) {
    const cover = evt.currentTarget;
    hide(cover);
    const curtain = document.querySelector(".curtain-ratio-keeper");
    curtain.classList.add("slide");
  }

  const cover = document.querySelector(".jacket");
  cover.addEventListener("click", coverClickHandler);
})();

const videoPlayer = (function makeVideoPlayer() {
  "use strict";

  let player = null;

  const tag = document.createElement("script");
  tag.src = "https://www.youtube.com/iframe_api";
  const firstScriptTag = document.getElementsByTagName("script")[0];
  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

  function onPlayerReady(event) {
    player = event.target;
    player.setVolume(100); // percent
  }
  let hasShuffled = false;

  function onPlayerStateChange(event) {
    const player = event.target;
    const shufflePlaylist = true;

    if (!hasShuffled) {
      player.setShuffle(shufflePlaylist);
      player.playVideoAt(0);
      hasShuffled = true;
    }
  }

  function addPlayer(video) {
    const playlist = "M7lc1UVf-VE";

    new YT.Player(video, {
      width: 640,
      height: 360,
      host: "https://www.youtube-nocookie.com",
      playerVars: {
        autoplay: 0,
        controls: 1,
        loop: 1,
        rel: 0,
        iv_load_policy: 3,
        cc_load_policy: 0,
        fs: 0,
        disablekb: 1,
        playlist
      },
      events: {
        onReady: onPlayerReady,
        onStateChange: onPlayerStateChange
      }
    });
  }

  return {
    addPlayer
  };
})();

function onYouTubeIframeAPIReady() {
  const wrapper = cover.parentElement;
  const frameContainer = wrapper.querySelector(".video");
  videoPlayer.addPlayer(frameContainer);
}

(function iife() {
  "use strict";

  function show(el) {
    el.classList.remove("hide");
  }

  function coverClickHandler(evt) {
    const wrapper = evt.currentTarget.parentElement;
    show(wrapper);
  }

  cover.addEventListener("click", coverClickHandler);
})();
html,
body {
  padding: 0;
  margin: 0;
}
body {
  height: 100vh;
  background: url(https://picsum.photos/id/1015/1500/1500) no-repeat;
  background-attachment: fixed;
  background-size: cover;
}
.outer {
  display: flex;
  min-height: 100vh;
  padding:8px 6px;
  box-sizing:border-box;
}
.inner{ 
  min-width: 40%;
  max-width: 640px;
  margin: auto;
}
.curtain-ratio-keeper {
  position: relative;
  padding-top: 56.25%;
  border-radius: 25px;
  height:0;
  overflow: hidden;
  border: 3px solid red;
}

.video-frame {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.jacket {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  margin: auto;
  cursor: pointer;
  z-index: 3;
}

.play {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  margin: auto;
  min-width: 70px;
  min-height: 70px;
  max-width: 30%;
  max-height: 30%;
  fill: red;
  filter: drop-shadow(3px 3px 3px rgba(0, 0, 0, 0.7));
  cursor: pointer;
}

.wrap iframe {
  position: absolute;
  top: -3px;
  left: -3px;
  width: calc(100% + 6px);
  height: calc(100% + 6px);
}

.wrap,
.jacket {
  position: absolute;
  top: -3px;
  left: -3px;
  width: calc(100% + 6px);
  height: calc(100% + 6px);
}
.hide {
  display: none;
}

.slide-wrap:before,
.slide-wrap:after {
  content: "";
  position: absolute;
  top: 0;
  width: 50%;
  height: 100%;
  transition: transform 5s linear;
  display: flex;
  align-items: center;
  background: url(https://picsum.photos/id/1015/1500/1500) no-repeat;
  background-attachment: fixed;
  background-size: cover;
  z-index: 2;
}
.slide-wrap:before {
  left: 0;
  justify-content: flex-end;
}
.slide-wrap:after {
  right: 0;
  justify-content: flex-start;
}
.slide .slide-wrap::before {
  transform: translateX(-100%);
}
.slide .slide-wrap::after {
  transform: translateX(100%);
}
<div class="outer">
    <div class="inner">
        <div class="curtain-ratio-keeper">
            <div class="video-wrapper">
                <div class="video-ratio-keeper slide-wrap">
                    <div class="wrap">
                        <div class="video video-frame"></div>
                    </div>
                </div>
            </div>
            <div class="jacket" title="Play">
                <svg class="play" width="100%" height="100%" viewBox="0 0 64 64">
                    <path d="M25.6,46.4L44.8,32L25.6,17.6V46.4z M32,0C14.3,0,0,14.3,0,32s14.3,32,32,32s32-14.3,32-32S49.7,0,32,0z
              M32,57.6C17.9,57.6,6.4,46.1,6.4,32S17.9,6.4,32,6.4S57.6,17.9,57.6,32S46.1,57.6,32,57.6z" />
                </svg>
            </div>
        </div>
    </div>
</div>


Solution

  • This is a rounding error with floating points when the width of your container is a non-integer (for example, 241.118px). The :before and :after elements will fill 50% of the container, but floating point math is imperfect and may round the result incorrectly, so rather than being 120.559px, it may be something like 120.554px. This causes the widths of the two pseudo-elements to not quite fill the container all the way, resulting in the gap you're seeing.

    A simple, albeit "band-aid-ish" fix is to just increase the width of the two pseudo-elements to something greater than 50% so even if there is a rounding error, the whole container will be covered. I originally suggested 51%, but since the gap will always be less than 1px, you are correct in using calc(50% + 1px) as well.

    .slide-wrap:before,
    .slide-wrap:after {
    
      width: calc(50% + 1px);
    
    }