CSS Solution Using Viewport Units
A pure CSS solution is available for achieving this effect, but there are some considerations to keep in mind:
It relies on using the vh
and vw
units, which may not be fully supported in all browsers, but support is getting better over time. This demonstrates the power of CSS3!
For this solution to work effectively, your target image needs to be sized relative to the viewport dimensions.
This solution also leverages media queries, a common technique for responsive web design.
Some adjustments might be necessary to fine-tune the positioning of the video element, but it has shown compatibility with modern browsers in my testing.
Insight Into Implementation
The critical aspect to understand here is how browsers handle scaling when using the "cover" property on an image. The transition occurs based on the ratio between viewport width and height, specifically suited to the image's aspect ratio.
While I'd like to claim mathematical precision in determining the threshold set in @media (min-width: 178vh)
, I confess it involved trial and error. By calculating the ratio from the original image dimensions of 3264 x 1836 (resulting in 1.7777777778), converting it to a hundredth value due to vh
and vw
unit scale, gives us approximately 178. Adjustments will be needed if the image dimensions change, requiring updates to the media query selector.
Further tweaks involve gauging the portion of the viewport occupied by the video in terms of vh
and vw
. Experimentation led me to these values, amid the confounding influence of beer-fueled problem-solving methods... quite inexplicable.
Implications and Workarounds
Upon additional testing, it seems that Webkit struggles with interpreting vh
within media queries, reluctance seemingly towards max-width
scenarios. Exploration reveals potential recourse via vmin
and vmax
implementations.
Later Realizations...
Confirming suspicions, Webkit disappoints once more regarding its handling of vh
and vw
in certain contexts. While the browser comprehends these units elsewhere, a blind spot persists in media queries, compounding frustrations among developers.
An alternative workaround involves utilizing the orientation
property within the media query. Although not foolproof, it mitigates failures barring square-ish viewports. Below, you'll find the revised code reflecting this adjustment.
Conclusion and Contingencies
If I were tasked with implementing this amidst existing browser disparities, I'd opt for the CSS approach supplemented by JavaScript intervention for unsupportive environments. Utilizing techniques like window.matchMedia
or libraries such as Enquire.js facilitates comprehensive cross-browser adaptability.
The code snippet now includes a JavaScript fallback mechanism, warranting refinement to avoid inadvertent class overrides on HTML elements. Prudence dictates exploring established solutions integrating event listeners and class manipulation to ensure seamless compatibility across diverse browsing environments.
// Credit to http://stackoverflow.com/questions/3437786/#answer-11744120
var viewportDimensions = function(){
var w = window,
d = document,
e = d.documentElement,
g = d.getElementsByTagName('body')[0];
return {
w: w.innerWidth || e.clientWidth || g.clientWidth,
h: w.innerHeight|| e.clientHeight|| g.clientHeight
};
};
window.matchMedia && (function(){
var test = window.matchMedia('screen and (min-width: 0vh)'), f;
// Failure is rare, predominantly affecting incompatible vh support in media queries.
if ( !test.matches ) {
// Respond to resize events
window.addEventListener('resize', (f=function(e){
// Acquire viewport dimensions
var vpd = viewportDimensions();
// Implement equivalent logic compared to the media query
if ( vpd.w > (1.78 * vpd.h) ) {
document.documentElement.className = 'min-width-178vh';
}
else {
document.documentElement.className = 'max-width-178vh';
}
}));
// Initial invocation
f();
}
})();
/* Centralizing coordinates, aligning with the fixed nature of "cover" usage */
.layer {
position: absolute;
left: 50%;
top: 50%;
width: 1px;
height: 1px;
}
/* Primarily reliant on viewport height, mirroring "cover" behavior during image expansion */
.video {
position: absolute;
width: 25.5vh;
left: -50.5vh;
top: -22.8vh;
background: #F00;
}
/* Addressing partial Webkit compatibility issue, adjusting calculations for non-squareish layouts */
@media screen and (orientation: landscape) {
.video {
top: -12.75vw;
left: -28.5vw;
width: 14.2vw;
}
}
/* Adaptation for changing scaling/cropping dynamics, pivot shifted towards viewport width */
@media screen and (min-width: 178vh) {
.video {
top: -12.75vw;
left: -28.5vw;
width: 14.2vw;
}
}
/* Reversing prior adjustments to accommodate Firefox rendering after Webkit rectification */
@media screen and (max-width: 178vh) {
.video {
width: 25.5vh;
left: -50.5vh;
top: -22.8vh;
}
}
/* Overriding media queries through JavaScript fallback triggers */
.min-width-178vh .video {
top: -12.75vw !important;
left: -28.5vw !important;
width: 14.2vw !important;
}
.max-width-178vh .video {
width: 25.5vh !important;
left: -50.5vh !important;
top: -22.8vh !important;
}
/* Initialization styles for structural setup */
.main {
top: 0;
left: 0;
position: absolute;
width: 100%;
height: 100%;
}
.inner {
position: absolute;
background: url("http://www.codelamp.co.uk/so/cover-video-pos-bg.jpg") no-repeat center center / cover;
background-color: #000;
width: 100%;
height: 100%;
}
<div class="main">
<div class="inner"></div>
<div class="layer">
<div class="video">
<video width="100%"></video>
</div>
</div>
</div>