mvasin / react-div-100vh

A workaround for the '100vh' issue in mobile browsers

Home Page:https://react-div-100vh.vercel.app

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Would something like this be possible?

rchrdnsh opened this issue · comments

Hi,

Been trying for months but can't get your component to work properly in my Gatsby JS React app. I'm thinking now, however, that maybe I need to do something like this:

@media (min-width: 50rem) {
  grid-template-rows: 20rvh 5rvh 5rvh 50rvh 20rvh;
  grid-template-columns: 1fr 3fr;
}

...in which I am using your Real Viewport Unit measurement as declarations of the grid-rows of a grid layout. Is something like this even possible? I'm using Viewport Units inside a styled-component, like so:

const App = styled(animated.div)`
  margin: 0;
  padding: 0;
  height: 100%;
  width: 100%;
  display: grid;
  grid-template-rows: 20rvh 70rvh 10rvh;
  grid-template-columns: repeat(3, 1fr);

  @media (min-width: 50rem) {
    grid-template-rows: 20vh 5vh 5vh 50vh 20vh;
    grid-template-columns: 1fr 3fr;
  }
`

...in combination with react-spring (hence the animated.div) inside of a Gatsby JS React app. It's all very convoluted, I know, but for me to even begin to use your component properly I need to do some fancy stuff in the gatsby-browser.js file, like so:

import React, { useEffect } from 'react'
import Div100vh from 'react-div-100vh'

const WrapperComponent = (props) => {
  useEffect(() => {
    window.onresize = function() {
      document.body.height = window.innerHeight;
    }

    window.onresize(); // called to initially set the height.
  }, []);

  return props.children;
}

export const wrapRootElement = ({ element }) => { 
  return (
  <WrapperComponent>
    <Div100vh>
      {element}
    </Div100vh>
  </WrapperComponent>
  )
}

I noticed in your docs that you recommend using a style tag and passing the rvh units in as an object, but I'm curious to know if it's possible to do what I have described above.

If you are interested, here is the issue in Gatsby's repo where some nice people are trying to help me out with this as well:

gatsbyjs/gatsby#15049

Any thoughts that you could share regarding this matter would be very much appreciated.

Thank you! XD

Hi @rchrdnsh,

First, Div100vh component controls only its own props. It parses rvh units (made up specifically for this component) and converts them to normal CSS units, but it happens only if you pass those to style prop; when you use a styled component, you feed rvh to the styled-components CSS parser that has no clue about rvh.

Second, I don't quite get why do use WrapperComponent, what it does is basically the same stuff Div100vh does, so you should choose between your own implementation or Div100vh, you probably don't need both.

so, somebody else had suggested using the wrapper component, although I don't fully understand why. This might be one of the reasons, as Gatsby doesn't return 'window' ???

I took a look at mvasin/react-div-100vh and it looks like it expects window to be defined (check the getWindowHeight function).

Gatsby is rendered server-side, and when it builds, window is undefined. This would cause your Gatsby site to crash on build.

From the docs:

If this is your problem you should see an error above like “window is not defined”. To fix this, find the offending code and either a) check before calling the code if window is defined so the code doesn’t run while Gatsby is building (see code sample below) or b) if the code is in the render function of a React.js component, move that code into componentDidMount which ensures the code doesn’t run unless it’s in the browser.

Is this the error you're running into?

If it is: since the error comes from an npm dependency, a solution is to ignore react-div-100vh on build through a webpack setting. Refer to Fixing third-party modules for details 🙂

If it isn't: can you provide error messages or a repo to test?

Then another person in the gatsby issues suggested doing this:

const WrapperComponent = (props) => {
  useEffect(() => {
    window.onresize = function() {
      document.body.height = window.innerHeight;
    }

    window.onresize(); // called to initially set the height.
  }, []);

  return props.children;
})

export const wrapRootElement = ({ element }) => {
  
  return (<WrapperComponent>
    <Div100vh>{element}</Div100vh>
  </WrapperComponent>)
}

...which also did not make sense to me, as it would seem that the wrapper is indeed duplicating functionality.

I just have no idea how to make this work for me, and I'm pulling my hair out at this point 😔

Also, how does this component work exactly?

If the <Div100vh> component is recalculating 100vh to equal the visual viewport, then can I nest another component inside of it that has height: 100vh; and that nested component will then adhere to the size set by the <Div100vh> component?

Or can I only use the <Div100vh> component to set the height and every nested component has to set its own height some other way, other than using vh units?

Using height: 100vh will get you exactly that, 100 viewport height, which is slightly more than actual visible area (when scroll is at the top). Try height: 100% inside <Div100vh>.

Also, I said before in another issue you opened, it would be best to provide a reproduction repository with as little code as possible, just to illustrate the issue. Chances are by the time you will come up with such a repository, you will figure out the solution by yourself.