Search code examples
htmlcssreactjsiframemedia-queries

Faking Iframe size so @media query is no applied


I have a website in which I can render a simple Html page on a route localhost:3000/static and a 3d scene on the normal route localhost:3000/. What I'm attempting to perform is, the media query transforms, which will only be applied if the route is localhost:3000/static, but not in the iframe. Because mobile the iframe (route: localhost:3000/) shows as it is on mobile, but I want it to show if it was on a deskop, without applying @medias.
Here is the css and how the page is being rendered in iframe:

.htmlScreen iframe {
  width: 1500px;
  height: 700px;
  border: none;
  background: #000;
}

 <Html
            transform
            prepend
            wrapperClass="htmlScreen"
            scale={0.35}
            distanceFactor={1.17}
            zIndexRange={[0, 0]}
          >
            <div
              onClick={(e) => {
                if (!isFocusOnHtml) e.preventDefault();
              }}
              onPointerEnter={(e) => {
                if (isFocusOnHtml) setIsPointerOnHtml(true);
              }}
              onPointerLeave={() => {
                if (isFocusOnHtml) setIsPointerOnHtml(false);
              }}
            >
              <iframe
                src="https://niltonsf.dev/static"
                title="myStaticWebsite"
                style={{ width: isMobile ? 1200 : 1500 }}
              />
            </div>
          </Html>

This is the @media:

@media screen and (max-width: 708px) {
  #root {
    background-color: red;
  }
}

As you can see on my 3d view, the background is being appplied, because I'm seeing this on mobile, but I don't want the media to be applied on this route, for the iframe.enter image description here


Solution

  • Well, I found a workaround on how to use media queries according to what you need or specific environments. This way I have made it, you can apply according to the size, environments, and any other variables you would like.
    Basically what I am using is a hook from usehooks-ts library:

    import { useMediaQuery } from "usehooks-ts";
    import { useState } from "react";
    
    export default function Header() {
      const mediumDevices = useMediaQuery("(max-width: 768px)");
      const smallDevices = useMediaQuery("(max-width: 350px)");
    

    With this, I can keep track of the media queries, and apply them as I want. "This looks the same as applying normal queries", yes it looks! Although you can add variables, for example, isMobile or isSpecialUser, etc, meaning, you can change the styling data according to the type of user, or mobile environment. In my case, I'm using styled-components to apply styles, and receive variables.

    This is a piece of my component and a example on how I'm using it:

    xport default function Header() {
      const [toggleMenu, setToggleMenu] = useState(false);
    
      const mediumDevices = useMediaQuery("(max-width: 768px)");
      const smallDevices = useMediaQuery("(max-width: 350px)");
    
      return (
        <HeaderCP mediumDevices={mediumDevices}>
          <Nav>
            <span className="nav_logo">Nilton A Schumacher F</span>
    
            <NavMenu
              smallDevices={smallDevices}
              mediumDevices={mediumDevices}
              toggleMenu={toggleMenu}
            >
              <Ul smallDevices={smallDevices} mediumDevices={mediumDevices}>
    

    On my styles I'm applying them as the following:

    import styled from "styled-components";
    
    interface MediaQuery {
      mediumDevices?: boolean;
      smallDevices?: boolean;
      toggleMenu?: boolean;
    }
    
    export const HeaderCP = styled.div<MediaQuery>`
      ${(props) => {
        let finalStyles = ``;
        finalStyles += `
            width: 100%;
            position: fixed;
            top: 0;
            left: 0;
            z-index: var(--z-fixed);
            background-color: var(--body-color);
        `;
        if (props.mediumDevices) {
          finalStyles += `        
            top: initial;
            bottom: 0;
          `;
        }
        return finalStyles;
      }}
    `;
    
    export const Nav = styled.nav.attrs({
      className: "container",
    })`
      height: calc(var(--header-height) + 1.5rem);
      display: flex;
      justify-content: space-between;
      align-items: center;
      column-gap: 1rem;
    `;
    
    export const NavMenu = styled.div<MediaQuery>`
      ${(props) => {
        let finalStyles = ``;
        if (props.mediumDevices) {
          finalStyles += `
            position: fixed;
            bottom: ${props.toggleMenu ? 0 : `-100%`};
            left: 0;
            right: 0;        
            width: 100vw - 50px;
            background-color: var(--body-color);        
            padding: 2rem 1.5rem 4rem;        
            box-shadow: 0 -1px 4px rgba(0, 0, 0, 0.15);
            border-radius: 1.5rem 1.5rem 0 0;
            transition: 0.3s;        
          `;
        }
        if (props.smallDevices) {
          finalStyles += `
            padding: 2rem 0.25rem 4rem;        
          `;
        }
        return finalStyles;
      }}
    `;
    

    This is just an example, I could add something like isMobile, isSamsung, isApple, etc. Meaning I can apply different styles to different devices.

    EDIT: In my case, I'm using Three.js, and rendering an iFrame with another route from my website. This solution was the one I was expecting. The iframe is not applying the mobile media queries on the main route (3d route) although If I go to the static website route, the media query is applied!