Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS vh units inside an iframe

Tags:

css

iframe

I'm trying to use CSS vh units inside of an iframe. I'm finding that they are scaled to the size of the iframe somehow. In other words, 100vh isn't the windowheight. It's set to the height of the iframe.

Does this seem right?

Is there a workaround?

like image 630
Union find Avatar asked Dec 03 '15 03:12

Union find


People also ask

Can I control CSS in an iframe?

We can use inline CSS for the iframe by using CSS inside the iframe tag. Example: The design of the HTML page is implemented as follows.

Can I style elements inside an iframe?

You can not change the styles of the page that resides within the iframe.

Does iframe need width and height?

The standard size of an iframe for desktop is a width of "560" and height of "315." Warning: Editing width but not Height or vice versa will result in a very narrow vertical or horizontal view of your video, so be sure to update both accordingly!


2 Answers

I know this is an old question, but as people move toward the vh unit, this question will become much more common.

To clarify, here's an example of the problem. We have an HTML file that loads an iframe:

<!DOCTYPE html> <html> <head></head> <style> iframe {     height: 50vh;     width: 100%; } </style> <body>     <iframe src="iframe.html"/> </body> </html> 

And its iframe:

<!DOCTYPE html> <html> <head></head> <style> div {     height: 50vh;     width: 100%;     background: blue; } </style> <body>     <div></div> </body> </html> 

The important thing to note here is that both the iframe and the iframe's div element are designated as having a height of 50vh. The intended behaviour may be that the iframe honor the parent context's viewport height or width. Instead, the result looks like this:

enter image description here

That is, the height of the blue element is ~25% of the browser window, instead of the expected 50% (100% of the iframe). Although we may wish the iframe to respect the viewport of its parent, this example makes a good case for how unintuitive that may be, though it surely would make the v* units more valuable for content being iframe'd in. The problem has to do with how viewport height is determined.

From the spec:

The viewport-percentage lengths are relative to the size of the initial containing block. When the height or width of the initial containing block is changed, they are scaled accordingly.

Both an iframe and the browser window can be the initial containing block, as they are both valid viewports. A viewport is not limited to the browser window, but instead is defined as a window or other viewing area on the screen through which users consult a document.

An iframe creates a nested browsing context when inserted into a document, and thus is its own viewport.

So yes, this is the intended behaviour - and unfortunately there is no pure CSS workaround - however, www139 has provided an example of how this can be accomplished using JavaScript. The problem with this begins when many elements' size are controlled using v* units.

like image 198
Jamie Counsell Avatar answered Sep 17 '22 14:09

Jamie Counsell


This is an excellent question. Sadly, I haven't been able to figure out a solution in CSS but I have been able to figure out a solution in JavaScript which I think is your best bet at the moment. Remember that the frames must be on the same domain for this to work.

Hope this helps. If this answer needs improvement, please comment below :-)

Solution in Theory (can't use here on SO because of frame origin issue):

window.addEventListener('load',function(){     initializeV();     function initializeV(){             //1% of the parent viewport width (same as 1vw):             var vw = window.parent.innerWidth/100;             //1% of the viewport height (same as 1vh):             var vh = window.parent.innerHeight/100;              //assign width and height to your v unit elements here     }      window.parent.addEventListener('resize',function(){           //when the browser window is resized; recalculate           initializeV();     }); }); 

Edit (Dec. 2018): In the comments, I was asked to supply an example. I can't do an exact example because the codepens on Stackoverflow load over a different frame origin than the page. However, I can mimic the effect. For practical applications, please reference the code snippet above. This snippet is meant merely to illustrate how it works.

Practical Application. Uses the concept explained above but without frame reference.

window.addEventListener('load',function(){          initializeV();          function initializeV(){                  //note: I can't use window.parent becuase the code snippet loads on a different frame than the parent page. See the other snippet for a practical example. This snippet is meant to merely illustrate the effect.                  //1% of the parent viewport width (same as 1vw):              	var vw = window.innerWidth/100;                  //1% of the viewport height (same as 1vh):              	var vh = window.innerHeight/100;                          //this is where the magic happens. Simply set width/height/whatever to a multiple of vw/vh and add 'px'. Dimensions must be in pixels since the vw/vh measurement is based on pixels.                document.getElementById('test').style.width = 30*vw+'px';                document.getElementById('test').style.height = 50*vh+'px';                  //assign width and height to your v unit elements here          }                    window.addEventListener('resize',function(){                //when the browser window is resized; recalculate                initializeV();          });      });
#test{  background:red;  }
<div id="test"></div>
like image 41
www139 Avatar answered Sep 19 '22 14:09

www139