Gatsby: [v2] Additional div wrapper

Created on 14 Aug 2018  ·  25Comments  ·  Source: gatsbyjs/gatsby

On one of my sites with the latest Gatsby I noticed that my layout is wrapped with an additional div:

<div style="outline:none" tabindex="-1" role="group">Normal content</div>

You can also see this behavior on https://next.gatsbyjs.org/
Why is that happening?

needs more info question or discussion

Most helpful comment

@janosh I meant the decision of reach/router maintainers to not provide a way to disable, or at least customize this wrapper div. I am a big proponent of semantic HTML and I am bummed that I have to deal with yet another wrapper div that only serves as a hook to a library that I barely knew about before facing this issue.

All 25 comments

@reach/router adds it so it can automatically manage the focus as part of making sure sites are usable by screen readers.

https://reach.tech/router/accessibility

I realize this is quite silly but I think it would be preferable if there was only one wrapping div.

It doesn't seems to be anything special about the reach div, would it perhaps be possible to merge the reach div with the wrapping id="___gatsby" div by adding the html attributes there instead?

It's unfortunately not possible to merge the two. Perhaps you could work with @reach/router on them reusing the div where React is mounted.

I need to add height: 100% to it but there's no class or id on it. I tried looking for it in the app but can't find it. Can you tell me how I can add an id to it?

@colmtuite It's not ideal but since the grouping div is the only child of <div id="___gatsby">, you can simply target it via

#___gatsby > * {
  height: 100%;
}

Update: A slightly better solution might be to use this more specific selector suggested by @ironblock here.

div[role="group"][tabindex] {
  height: 100%;
}

Update 2: Back in 2018, this was not the case but nowadays, the div in question has an id of gatsby-focus-wrapper. So the selector can be much less obscure:

#gatsby-focus-wrapper {
  height: 100%;
}

spit

Relevant issue: https://github.com/reach/router/issues/63

I personally think this is misguided and is a source of issues for those not using styled components.

@kaishin Could you expand on what you mean? What exactly is misguided?

@janosh I meant the decision of reach/router maintainers to not provide a way to disable, or at least customize this wrapper div. I am a big proponent of semantic HTML and I am bummed that I have to deal with yet another wrapper div that only serves as a hook to a library that I barely knew about before facing this issue.

I understand your point now and quite agree. I feel much the same about non-semantic markup.
I was just confused by the end of your comment

... is a source of issues for those not using styled components

as I don't see why people who _are_ using styled-components would be unaffected.

I can't believe this issue has been closed with so unreasonable solution.

@danielo515 Well, the issue is with a dependency, so it's somewhat understandable.

This comment offers a CSS workaround: https://github.com/reach/router/issues/63#issuecomment-428050999

as I don't see why people who are using styled-components would be unaffected.

@janosh Since I opened this issue I didn't have any problems whatsoever with styling. So what's the problem here actually?

@LekoArts Unsemantic markup that breaks CSS solutions for keeping the footer at the bottom of the window even in the absence of sufficient content. Using styled-components and knowing a workaround CSS selector doesn't make the wrapper div any more semantic.

Natively, when you click somewhere on the body and then press tab it will focus the nearest focusable element. However this wrapper means clicking on the body will focus the wrapper, resetting the tab order to the beginning instead of near the element. I'm not sure if this is an accessibility problem but it's something I noticed when trying to click near an element and then press tab focus it.

@colmtuite Consider to use something like height: 100vh;

@skinenbayev @colmtuite
Or with flex,

div[role="group"][tabindex] {
  display: flex;
  flex-direction: column;
  flex-grow: 1;
}

@Schmerb I think setting 100vh to your css dedicated class is more convenient way than manipulating with some generated code.

@skinenbayev
I guess I should have clarified...100vh is great if you want your app to have a fixed height the same size as your viewport...

BUT if you need the app to take up all available space

(essentially what everyone with height: 100% is attempting but is most likely failing due to parent not having a set height)

then Flexbox to the rescue.

To further clarify my specific case, screenshots of both attempts:
The blue/orange border is a /page component. The random 'hook' div that Gatsby places is the white space. With height: 100vh the white space can be seen extending well below the bottom of the viewport...pushing the footer off the page even though the page itself essentially has no content.

Using flex with its main axis switched (flex-direction: column instead of default flex-direction: row) and flex-grow property, you can see it very nicely takes up all available space.

with height: 100vh;
Screen Shot 2019-03-18 at 3 40 21 PM

with display: flex; flex-direction: column; flex-grow: 1;
Screen Shot 2019-03-18 at 3 40 11 PM

All that I see are workarounds for a problem that should not even exist.
What if your target browser does not support flexbox?

I've had issues as well with a bug when setting `height: 100vh' where when scrolling is required, I get a double scrollbar in chrome.

The way I've solved a similar problem is rather than use height: 100vh;, is to add min-height: 100vh; to my wrapping Layout component. When you combine that with something like setting:
grid-template-areas: 'Header' 'Content' 'Footer';
grid-template-rows: auto 1fr auto;
min-height: 100vh;

Now, the wrapping component will always be _at least_ the height of the view port, but if the content is large enough to require scrolling, the footer element will be pushed to remain at the bottom of the screen.

But (big but!) unfortunately, grid has less browser support than flexbox, but it feels less 'hacky' personally.

Maybe not an answer to help with not having flex support, but perhaps a neater way to get a footer to stick to the bottom of the page?

Unfortunately, while the line of code in question addresses accessibility, it also causes an accessibility error. I've logged an issue at https://github.com/reach/router/issues/257.

Be aware that 100vh might mean something different to Android browsers.
Quick googling unveils example: https://stackoverflow.com/q/30148956

For some reason div[role="group"][tabindex] is not applying any style to that div. I had to specify the id #gatsby-focus-wrapper

Still no reasonable solution to the height problem?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dustinhorton picture dustinhorton  ·  3Comments

andykais picture andykais  ·  3Comments

KyleAMathews picture KyleAMathews  ·  3Comments

kalinchernev picture kalinchernev  ·  3Comments

totsteps picture totsteps  ·  3Comments