-
Notifications
You must be signed in to change notification settings - Fork 124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix heading padding FOUC (option 3 with modifications: sticky header) #1939
Conversation
Any thoughts on the conclusion @damithc? Does this make sense to a MarkBind user? (complexity / insufficient configuration / etc.) 👀 |
While a bit more complex than usual, I think it is still acceptable if we fine-tune the description to be bit more noob-friendly. |
packages/core-web/src/index.js
Outdated
window.addEventListener('resize', () => { | ||
if (window.innerWidth > 767 && headerSelector.hasClass('hide-header')) { | ||
if (window.innerWidth > 767 && isHidden) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a heads up, I think will have to update the fixed-header-padding
height one more time during resize.
Currently there will be a large padding if the header reappears during resize:
MarkBind.-.User.Guide_.Presentational.Components.-.Google.Chrome.2022-05-29.00-48-02.mp4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some comments on the UG :)
@jonahtanjz @tlylt @damithc Thanks for the reviews! After letting this sit for a while I realised there was a very simple way I missed previously to achieve the best result:
The gist:
Concerns:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some self-commenting on the changes to hopefully make reviewing easier :)
return; | ||
} | ||
|
||
window.addEventListener('resize', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a heads up, I think will have to update the fixed-header-padding height one more time during resize.
I've the "merged" this fix from the other PR into the resizeObserver changes below
// reset overflow when header shows again to allow content | ||
// in the header such as search dropdown etc. to overflow | ||
if (headerMaxHeight === '100%') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
most of the changes here (resizeObserver, this line, isHidden) are necessary due to switching to transform translate
for hiding the header (height change dosen't work with position: sticky
), which should be simpler (I think) to deal with too.
header[sticky] { | ||
position: sticky; | ||
top: 0; | ||
transition: transform 0.3s ease-in-out; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
height transition won't work now since its sticky
Perhaps give one more example of how the variable can be used? Having more than one example helps to identify which part of the code the user needs to change when applying to another context. |
Added, though - I avoided this previously as it requires referencing some of our internal implementation details: We only have one more example use case in place otherwise which is even more obscure (setting up the header hiding transition for mobile devices). I could also remove the tip and second example entirely and just focus on the first one to avoid confusion. Wdyt? @damithc |
Is it possible to give examples of how they can use it (rather than how we use it)? Yes, if it is unlikely users will want to use that variable, we can skip it altogether. |
I can't think of any right now, at least. =X Maybe @jonahtanjz @tlylt have some ideas. I can go ahead with skipping the tip + second example altogether otherwise.
To be clear though, its still important for the primary use case (the first example), or at least, for the author to take note of it (e.g. accidental removal) when altering layout files. Otherwise, the site / page nav will be hidden behind the header as you scroll down. Similar to the slightly awkward |
Sorry, realised I haven't handled a few more implementation edge cases. Will re-ping once its ready. |
Use the bounding box of the sibling element next to the sticky header to figure out if the page has scrolled past the header. As the bounding rectangle of the sticky element changes to as if it is fixed once position sticky "activates".
I don't think there are any good examples other than if the user decides to not use a Other than that, I think the documentation looks good :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just noticed this, will also need to collapse the dropdown when the header is hidden on mobile. Seems like the dropdown will auto hide on blur
so maybe we can trigger a blur
event inside the hideHeader
method?
Landing.Page.-.Google.Chrome.2022-06-12.13-29-44.mp4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really related to this PR, but wondering if you guys also experience the weird behavior of having the header reappearing even if I am scrolling downwards? It happens sporadically when browsing the site on a mobile (actual phone, not on desktop inspector). I tried on iPhone Safari & Chrome and both have this effect. It contradicts the point:
To preserve screen real estate, the header is hidden on devices with a width of less than 767px when the user scrolls down, and automatically re-shown when the page is scrolled up.
...but I think it has been like this all along.
The second example on page anchors can be a little confusing to the users so I think this can be removed.
Agree that in the current state, the example is a little confusing (because it is how we use it and not how they can use it). I think either removing it or putting it in a closed panel is fine. Can't really think of any other common use cases either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jonahtanjz @tlylt I've removed the second example since everyone is in agreement, and touched up the relevant parts from your reviews. Also edited the example a little.
The implementation should be ready now too :)
Just noticed this, will also need to collapse the dropdown when the header is hidden on mobile. Seems like the dropdown will auto hide on blur so maybe we can trigger a blur event inside the hideHeader method?
ouch, nice catch =X. Miscopied one of the headerSelector.css('overflow', 'hidden');
-> headerSelector.css('overflow', '')
.
Some more self comments to help reviewing:
@@ -56,28 +56,28 @@ mark { | |||
margin: 0 auto; | |||
min-width: 0; | |||
max-width: 1000px; | |||
overflow-x: auto; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Documenting the layout file changes for review + future release changelog noting (should be simplified though I think =P)
1st of 3 important changes in the layout file:
This might be somewhat controversial, but is unfortunately necessary with a sticky header. At least, I haven't found another solution.
The issue (without this) occurs on pages that overflow (e.g. "formatting contents" page or "Using html javascript and css"). The nearest scrolling ancestor which is the page / root element expands to accomodate the overflown content, which in turn does 2 things:
window.innerWidth/Height
are erroneous (although there is an easy alternative for thisdocument.documentElement.clientWidth/Height
)- More important is that the way sticky positioning is defined, the sticky positioning goes haywire (with or without our header height detection)
Gif demo (open image in new tab to view in order): there are 3 settings here.
- The first shows proper function of sticky positioning when the viewport zooms out to the entire page.
- The second showcases how the page loads on a mobile device normally, observe how the sticky positioning completely goes haywire as the page is "zoomed" (although it dosen't quite appear like that to the reader).
- The third is same as the second, except I temporarily toggled off the header hiding (the
translateY
) to show the issue is really unrelated to header hiding / anything we are doing.
You can try removing the overflow-x
when testing this PR to see the issue better, its a little hard to present on a gif.
The fix: I've set overflow-x
on the content wrapper which significantly changes ux on mobile devices (but just pages that overflow).
Pros:
- As a nice side effect, this change "fixes" Fixed headers should span only the viewport space #1741.
- Overflown content is still usable by swiping left / right.
Cons:
- On desktop devices, although very very unlikely (since there is enough space for overflown content on mobile to fully "expand" - including our embeds), if there is overflow, I would still like to point out the horizontal scroll bar is only visible at the bottom of the content wrapper. (which can be confusing)
- add to that that site development should usually be done on a desktop device (so authors will likely limit content sizes to a reasonable degree (e.g. images))
- You'll no longer be able to "zoom out" on mobile (though arguably this could also be a plus for mobile ux)
Not sure if there's a better solution =, but imo its a good enough compromise.
position: sticky; | ||
top: 0; | ||
top: var(--sticky-header-height); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2nd change per the docs
max-width: 300px; | ||
max-height: calc(100vh - var(--sticky-header-height)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
last change: 100vh
worked before as it took into account padding-top
from fixed-header-padding
.
With the shift to top: var(--sticky-header-height);
the content boxes actually do shift down, so we need to minus that off.
The other changes (90vh
) is just to standardise the way this is done in the layout stylesheet between the site and page nav to make things simpler.
1) Bounding box is calculated as if 'position: fixed' when sticky is "activated". | ||
Revert the position to 'static' temporarily to avoid this. | ||
|
||
Seems to be harmless UX wise, even on extremely slow devices. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change here is pretty much as explained in the comment, although I would like to get some help with testing this ^ in particular on more devices. (whether the header ever "flickers" right before it is being hidden)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested and works fine on my end 👍
I've encountered this as well, have a hunch as to why this occuring (still is too, I think). As the debounce duration is pretty short, and touchscreens are quite sensitive (as opposed to chrome emulator operated by a mouse), there's a chance this is functioning correctly, but the change in page offset isn't "thresholded" enough. (currently we just do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM on my end 👍
Will merge once the temporary announcement is removed :)
@ang-zeyu I think will need you to update the commit message as well since the implementation has changed :) |
Thanks for the reminder, updated |
What is the purpose of this pull request?
Resolves #1560
Follow up on #1929, #1930, #1931 and discussion in #1560
Overview of changes:
Anything you'd like to highlight / discuss:
Testing instructions:
<header fixed>
(anywhere in the userguide exceptuserGuide/stickyDemo.html
) should behave as before, except without the FOUC. This includes the mobile site / page nav.<header sticky>
(new feature) performs as described in the documentation. The mobile site / page nav should perform identically to that of<header fixed>
(currently broken - tbddone!)Proposed commit message: (wrap lines at 72 characters)
Implement sticky header
Since no assumptions of the user's header's height can be made at build
time, runtime style detection is required to calculate the header
height used in the fixed-header-padding class. This causes a flash of
unstyled content briefly before this detection is done
(the content is hidden behind the header).
Let's implement a sticky header instead, which "natively" offsets
content below it.
It should be noted that header height detection is still required
however, particularly for offsetting the sticky positioning of the
navigation menus on the side (top: var(--sticky-header-height)), since
they are (usually) much shorter than the main content element.
This header height is now exposed using the css variable
var(--sticky-header-height) for use in the user layout files.
Checklist: ☑️